text: import sys
  import os.path
  from PackageUtils import PackageUtils
  from Logger import Logger
  from ToolChainUtils import ToolChainUtils
  from CommandUtils import CommandUtils
  from constants import constants
  from SpecData import SPECS
  from StringUtils import StringUtils
  from Sandbox import Chroot, Container
  
  class PackageBuilder(object):
      def __init__(self, mapPackageToCycles, sandboxType):
          # will be initialized in buildPackageFunction()
          self.logName = None
          self.logPath = None
          self.logger = None
          self.package = None
          self.version = None
          self.doneList = None
          self.sandboxType = sandboxType
          self.sandbox = None
          self.mapPackageToCycles = mapPackageToCycles
          self.listNodepsPackages = ["glibc", "gmp", "zlib", "file", "binutils", "mpfr",
                                     "mpc", "gcc", "ncurses", "util-linux", "groff", "perl",
                                     "texinfo", "rpm", "openssl", "go"]
  
      def build(self, pkg, doneList):
          packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg)
          #do not build if RPM is already built
          #test only if the package is in the testForceRPMS with rpmCheck
          #build only if the package is not in the testForceRPMS with rpmCheck
  
          if not constants.rpmCheck or packageName in constants.testForceRPMS:
              if self._checkIfPackageIsAlreadyBuilt(packageName, packageVersion, doneList):
                  return
  
          self._buildPackagePrepareFunction(packageName, packageVersion, doneList)
          try:
              self._buildPackage()
          except Exception as e:
              # TODO: self.logger might be None
              self.logger.exception(e)
              raise e
  
      def _buildPackage(self):
          try:
              self.sandbox.create(self.package + "-" + self.version)
  
              tUtils = ToolChainUtils(self.logName, self.logPath)
              if self.sandbox.hasToolchain():
                  tUtils.installExtraToolchainRPMS(self.sandbox, self.package, self.version)
              else:
                  tUtils.installToolchainRPMS(self.sandbox, self.package, self.version, availablePackages=self.doneList)
  
              listDependentPackages, listTestPackages, listInstalledPackages, listInstalledRPMs = (
                  self._findDependentPackagesAndInstalledRPM(self.sandbox))
  
              pkgUtils = PackageUtils(self.logName, self.logPath)
  
              if listDependentPackages:
                  self.logger.debug("Installing the build time dependent packages......")
                  for pkg in listDependentPackages:
                      packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg)
                      self._installPackage(pkgUtils, packageName, packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs)
                  for pkg in listTestPackages:
                      flag = False
                      packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg)
                      for depPkg in listDependentPackages:
                          depPackageName, depPackageVersion = StringUtils.splitPackageNameAndVersion(depPkg)
                          if depPackageName == packageName:
                              flag = True
                              break;
                      if flag == False:
                          self._installPackage(pkgUtils, packageName,packageVersion, self.sandbox, self.logPath,listInstalledPackages, listInstalledRPMs)
                  pkgUtils.installRPMSInOneShot(self.sandbox)
                  self.logger.debug("Finished installing the build time dependent packages....")
  
              pkgUtils.adjustGCCSpecs(self.sandbox, self.package, self.version)
              pkgUtils.buildRPMSForGivenPackage(self.sandbox, self.package, self.version,
                                                self.logPath)
              self.logger.debug("Successfully built the package: " + self.package)
          except Exception as e:
              self.logger.error("Failed while building package: " + self.package)
              self.logger.debug("Sandbox: " + self.sandbox.getID() +
                                " not deleted for debugging.")
              logFileName = os.path.join(self.logPath, self.package + ".log")
              fileLog = os.popen('tail -n 100 ' + logFileName).read()
              self.logger.info(fileLog)
              raise e
          if self.sandbox:
              self.sandbox.destroy()
  
      def _buildPackagePrepareFunction(self, package, version, doneList):
          self.package = package
          self.version = version
          self.logName = "build-" + package + "-" + version
          self.logPath = constants.logPath + "/" + package + "-" + version
          if not os.path.isdir(self.logPath):
              cmdUtils = CommandUtils()
              cmdUtils.runCommandInShell("mkdir -p " + self.logPath)
          self.logger = Logger.getLogger(self.logName, self.logPath, constants.logLevel)
          self.doneList = doneList
  
          if self.sandboxType == "chroot":
              sandbox = Chroot(self.logger)
          elif self.sandboxType == "container":
              sandbox = Container(self.logger)
          else:
              raise Exception("Unknown sandbox type: " + sandboxType)
  
          self.sandbox = sandbox
  
      def _findPackageNameAndVersionFromRPMFile(self, rpmfile):
          rpmfile = os.path.basename(rpmfile)
          releaseindex = rpmfile.rfind("-")
          if releaseindex == -1:
              self.logger.error("Invalid rpm file:" + rpmfile)
              return None
          pkg = rpmfile[0:releaseindex]
          return pkg
  
      def _findInstalledPackages(self, sandbox):
          pkgUtils = PackageUtils(self.logName, self.logPath)
          listInstalledRPMs = pkgUtils.findInstalledRPMPackages(sandbox)
          listInstalledPackages = []
          for installedRPM in listInstalledRPMs:
              pkg = self._findPackageNameAndVersionFromRPMFile(installedRPM)
              if pkg is not None:
                  listInstalledPackages.append(pkg)
          return listInstalledPackages, listInstalledRPMs
  
      def _checkIfPackageIsAlreadyBuilt(self, package, version, doneList):
          basePkg = SPECS.getData().getSpecName(package) + "-" + version
          return basePkg in doneList
  
  
      def _findRunTimeRequiredRPMPackages(self, rpmPackage, version):
          return SPECS.getData().getRequiresForPackage(rpmPackage, version)
  
      def _findBuildTimeRequiredPackages(self):
          return SPECS.getData().getBuildRequiresForPackage(self.package, self.version)
  
      def _findBuildTimeCheckRequiredPackages(self):
          return SPECS.getData().getCheckBuildRequiresForPackage(self.package, self.version)
  
      def _installPackage(self, pkgUtils, package, packageVersion, sandbox, destLogPath,
                          listInstalledPackages, listInstalledRPMs):
          rpmfile = pkgUtils.findRPMFile(package,packageVersion);
          if rpmfile is None:
              self.logger.error("No rpm file found for package: " + package + "-" + packageVersion)
              raise Exception("Missing rpm file")
          specificRPM = os.path.basename(rpmfile.replace(".rpm", ""))
          pkg = package+"-"+packageVersion
          if pkg in listInstalledPackages:
                  return
          # mark it as installed -  to avoid cyclic recursion
          listInstalledPackages.append(pkg)
          listInstalledRPMs.append(specificRPM)
          self._installDependentRunTimePackages(pkgUtils, package, packageVersion, sandbox, destLogPath,
                                                listInstalledPackages, listInstalledRPMs)
          noDeps = False
          if (package in self.mapPackageToCycles or
                  package in self.listNodepsPackages or
                  package in constants.noDepsPackageList):
              noDeps = True
          pkgUtils.prepRPMforInstall(package,packageVersion, noDeps, destLogPath)
  
      def _installDependentRunTimePackages(self, pkgUtils, package, packageVersion, sandbox, destLogPath,
                                           listInstalledPackages, listInstalledRPMs):
          listRunTimeDependentPackages = self._findRunTimeRequiredRPMPackages(package, packageVersion)
          if listRunTimeDependentPackages:
              for pkg in listRunTimeDependentPackages:
                  if pkg in self.mapPackageToCycles:
                      continue
                  packageName, packageVersion = StringUtils.splitPackageNameAndVersion(pkg)
                  rpmfile = pkgUtils.findRPMFile(packageName, packageVersion)
                  if rpmfile is None:
                      self.logger.error("No rpm file found for package: " + packageName + "-" + packageVersion)
                      raise Exception("Missing rpm file")
                  latestPkgRPM = os.path.basename(rpmfile).replace(".rpm", "")
                  if pkg in listInstalledPackages and latestPkgRPM in listInstalledRPMs:
                      continue
                  self._installPackage(pkgUtils, packageName,packageVersion, sandbox, destLogPath,listInstalledPackages, listInstalledRPMs)
  
      def _findDependentPackagesAndInstalledRPM(self, sandbox):
          listInstalledPackages, listInstalledRPMs = self._findInstalledPackages(sandbox)
          self.logger.debug(listInstalledPackages)
          listDependentPackages = self._findBuildTimeRequiredPackages()
          listTestPackages=[]
          if constants.rpmCheck and self.package in constants.testForceRPMS:
              # One time optimization
              if constants.listMakeCheckRPMPkgWithVersionstoInstall is None:
                  constants.listMakeCheckRPMPkgWithVersionstoInstall=[]
                  for package in constants.listMakeCheckRPMPkgtoInstall:
                      version = SPECS.getData().getHighestVersion(package)
                      constants.listMakeCheckRPMPkgWithVersionstoInstall.append(package+"-"+version)
  
              listDependentPackages.extend(self._findBuildTimeCheckRequiredPackages())
              testPackages = (set(constants.listMakeCheckRPMPkgWithVersionstoInstall) -
                              set(listInstalledPackages) -
                              set([self.package+"-"+self.version]))
              listTestPackages=list(set(testPackages))
              listDependentPackages = list(set(listDependentPackages))
          return listDependentPackages, listTestPackages, listInstalledPackages, listInstalledRPMs
  