Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

package com.erggroup.buildtool.ripple;

import java.io.File;

import java.util.Iterator;
import java.util.Vector;

import org.apache.log4j.Logger;

public class Package
{
  /**name of package, must not contain spaces
   * @attribute
   */
  String mName = new String();

  /**package scope
   * @attribute
   */
  String mExtension = new String();

  /**instance identifier
   * @attribute
   */
  String mVersion = new String();

  /**unique identifier
   * for daemon builds = mName + mExtension
   * for escrow builds = mName + mVersion + mExtension
   * @attribute
   */
  String mAlias = new String();

  /**clearcase vob location, must not contain spaces
   * @attribute
   */
  String mLocation = new String();

  /**clearcase source file instance identifier
   * @attribute
   */
  String mLabel = new String();

  /**build standards
   * @attribute
   */
  Vector mBuildStandardCollection = new Vector();

  /**GBE_MACHTYPE used to build generic packages for this baseline
   * only has meaning in the daemon build, not the escrow build
   * accessed by BuildStandard::getPlatform, getBuildStandard
   * @attribute
   */
  public static final String mGenericMachtype = System.getenv("GBE_MACHTYPE");

  /**build dependencies by package alias
   * @attribute
   */
  Vector mDependencyCollection = new Vector();

  /**primary package version key pv_id in database
   * @attribute
   */
  int mId;

  /**indication of the nature of change
   * @attribute
   */
  Package.VersionNumberingStandard mChangeType = new VersionNumberingStandard();

  /**determines what field is rippled on a package version whose dependencies have changed
   * @attribute
   */
  Package.VersionNumberingStandard mRippleField = new VersionNumberingStandard();

  /**interested owners
   * @attribute
   */
  Vector mBuildFailureEmailCollection = new Vector();

  /**when true will trigger unit tests as part of the package build phase in daemon mode
   * @attribute
   */
  boolean mHasAutomatedUnitTests = false;

  /**when true, do not include in a build in daemon mode
   * @attribute
   */
  boolean mDoNotRipple = false;

  /**when true, do not ripple this package through packages which are dependent upon it in daemon mode
   * @attribute
   */
  boolean mAdvisoryRipple = false;

  /**determines the build file the package is built in, or not
   *  1 buildfile 1 etc
   *  0 not yet processed (initial value)
   * -1 not reproducible
   * -2 not reproducible on the build platforms configured for this release
   * -3 do not ripple
   * -4 directly dependent on package versions not in the baseline
   * -5 indirectly dependent on package versions which are not reproducible
   *    because of -1, -2 (escrow), -3 (daemon), -4
   * @attribute
   */
  int mBuildFile = 0;

  /**build dependencies by package
   * @attribute
   */
  Vector mPackageDependencyCollection = new Vector();

  /**used for escrow build purposes
   * set true when a package has been processed
   * @attribute
   */
  boolean mProcessed = false;

  /**set true for WIP package versions
   * only used in daemon mode
   * @attribute
   */
  boolean mDirectlyPlanned = false;

  /**set true when it is determined to be ripple built
   * @attribute
   */
  boolean mIndirectlyPlanned = false;

  /**build dependencies by pv_id (-1 or not used for planned dependencies)
   * @attribute
   */
  Vector mDependencyIDCollection = new Vector();

  /**unique pkg_id in the database
   * used for querying package version existence in the database in daemon mode
   * @attribute
   */
  int mPid;

  /**Logger
   * @attribute
   */
  private static final Logger mLogger = Logger.getLogger(Package.class);

  /**dpkg archive location
   * @attribute
   */
  public static final String mGbeDpkg = System.getenv("GBE_DPKG");

  /**deploy archive location
   * @attribute
   */
  public static final String mGbeDply = System.getenv("GBE_DPLY");

  /**true if the package exists in the dpkg or deploy archive
   * @attribute
   */
  private boolean mArchivalExistence = true;

  /**constructor
   */
  Package(int pv_id, String pkg_name, String v_ext, String alias, 
          String pkg_label, String src_path, char change_type)
  {
    mLogger.debug("Package 1: pv_id " + pv_id + " pkg_name " + pkg_name + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path + " change_type " + change_type);
    mId = pv_id;
    mName = pkg_name;
    mVersion = "0.0.0000";
    mExtension = v_ext;
    mAlias = alias;
    mLabel = pkg_label;
    mLocation = src_path;
    
    if (change_type == 'M')
    {
      mChangeType.setMajor();
    }
    else if (change_type == 'N')
    {
      mChangeType.setMinor();
    }
    else
    {
      mChangeType.setPatch();
    }
  }

  /**constructor
   */
  Package(int pv_id, String pkg_name, String pkg_version, String v_ext, 
          String alias, String pkg_label, String src_path, 
          char ripple_field)
  {
    mLogger.debug("Package 2: pv_id " + pv_id + " pkg_name " + pkg_name + " pkg_version " + pkg_version + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path + " ripple_field " + ripple_field);
    mId = pv_id;
    mName = pkg_name;
    mVersion = pkg_version;
    int endindex = mVersion.length() - v_ext.length();
    
    if ( endindex > 0 )
    {
      mVersion = mVersion.substring(0, endindex);
    }
    
    mExtension = v_ext;
    mAlias = alias;
    mLabel = pkg_label;
    mLocation = src_path;
    
    if (ripple_field == 'M')
    {
      mRippleField.setMajor();
    }
    else if (ripple_field == 'm')
    {
      mRippleField.setMinor();
    }
    else if (ripple_field == 'p')
    {
      mRippleField.setPatch();
    }
  }

  /**constructor
   */
  Package()
  {
    mLogger.debug("Package 3");
    mId = 0;
    mName = "null";
    mExtension = "null";
    mAlias = "null";
    mLabel = "null";
    mLocation = "null";
  }

  /**returns true if mBuildStandardCollection is not empty
   */
  boolean isReproducible()
  {
    mLogger.debug("isReproducible on Package " + mName);
    boolean retVal = false;
    
    if ( mBuildStandardCollection.size() > 0 )
    {
      retVal = true;
    }
    
    mLogger.info("isReproducible returned " + retVal);
    return retVal;
  }

  /**returns true if at least one of its BuildStandards has mWin32 or mGeneric true
   */
  boolean isWin32Built()
  {
    mLogger.debug("isWin32Built on Package " + mName);
    boolean retVal = false;
    for (Iterator it = mBuildStandardCollection.iterator(); it.hasNext(); )
    {
      BuildStandard buildStandard = (BuildStandard) it.next();

      if (buildStandard.getWin32() || buildStandard.getGeneric())
      {
        retVal = true;
        break;
      }
    }

    mLogger.info("isWin32Built returned " + retVal);
    return retVal;
  }

  /**returns true if at least one of its BuildStandards has mSolaris or mGeneric true
   */
  boolean isSolarisBuilt()
  {
    mLogger.debug("isSolarisBuilt on Package " + mName);
    boolean retVal = false;
    for (Iterator it = mBuildStandardCollection.iterator(); it.hasNext(); )
    {
      BuildStandard buildStandard = (BuildStandard) it.next();

      if (buildStandard.getSolaris() || buildStandard.getGeneric())
      {
        retVal = true;
        break;
      }
    }

    mLogger.info("isSolarisBuilt returned " + retVal);
    return retVal;
  }

  /**returns true if at least one of its BuildStandards has mLinux or mGeneric true
   */
  boolean isLinuxBuilt()
  {
    mLogger.debug("isLinuxBuilt on Package " + mName);
    boolean retVal = false;
    for (Iterator it = mBuildStandardCollection.iterator(); it.hasNext(); )
    {
      BuildStandard buildStandard = (BuildStandard) it.next();

      if (buildStandard.getLinux() || buildStandard.getGeneric())
      {
        retVal = true;
        break;
      }
    }

    mLogger.info("isLinuxBuilt returned " + retVal);
    return retVal;
  }

  /**returns true if at least one of its BuildStandards has mGeneric true
   */
  boolean isGeneric()
  {
    mLogger.debug("isGeneric on Package " + mName);
    boolean retVal = false;
    for (Iterator it = mBuildStandardCollection.iterator(); it.hasNext(); )
    {
      BuildStandard buildStandard = (BuildStandard) it.next();

      if (buildStandard.getGeneric())
      {
        retVal = true;
        break;
      }
    }

    mLogger.info("isGeneric returned " + retVal);
    return retVal;
  }

  /**applies the required version number change
   */
  void applyPV(ReleaseManager releaseManager, int rtag_id) throws Exception
  {
    mLogger.debug("applyPV on Package " + mName);
    // three scenarios, only applyPV for 2 of them
    // WIP exists:                      mDirectlyPlanned == true;   mIndirectlyPlanned == true; mArchivalExistence don't care - applyPV
    // Package version is out of date:  mDirectlyPlanned == false;  mIndirectlyPlanned == true; mArchivalExistence == true    - applyPV
    // Package version does not exist:  mDirectlyPlanned == false;  mIndirectlyPlanned == true; mArchivalExistence == false   - do not applyPV
    if ( !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence )
    {
      // the package has an mIndirectlyPlanned flag set true in daemon mode because the package does not exist in an archive
      // do not apply a different package version
      mLogger.info("applyPV !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence on Package " + mName);
      return;
    }
    
    int major = 0;
    int minor = 0;
    int patch = 1000;

    String field[] = mVersion.split("\\D");
    
    if ( field.length == 3 )
    {
      major = Integer.parseInt(field[0]);
      minor = Integer.parseInt(field[1]);
      patch = Integer.parseInt(field[2]);
    }
    else
    {
      // cannot work with non standard versioning
      mLogger.error("applyPV cannot work with non standard versioning");
      return;
    }

    if ( patch < 1000 && field[2].substring(0, 1).compareTo("0") != 0 )
    {
      mLogger.info("applyPV accomodate old style mVersion of the form 1.0.1");
      patch = patch * 1000;
    }
      
    // mChangeType overrides mRippleField
    do
    {
      if ( mChangeType.mMajor )
      {
        major++;
        mLogger.info("applyPV mChangeType.mMajor " + major);
        minor = 0;
        patch = 0;
      }
      else if ( mChangeType.mMinor )
      {
        minor++;
        mLogger.info("applyPV mChangeType.mMinor " + minor);
        patch = 0;
      }
      else if ( mChangeType.mPatch )
      {
        do
        {
          patch++;
        } while ( ( patch / 1000 ) * 1000 != patch );
        mLogger.info("applyPV mChangeType.mPatch " + patch);
      }
      else
      {
        if ( mRippleField.mMajor )
        {
          major++;
          mLogger.info("applyPV mRippleField.mMajor " + major);
          minor = 0;
          patch = 0;
        }
        else if ( mRippleField.mMinor )
        {
          minor++;
          mLogger.info("applyPV mRippleField.mMinor " + minor);
          patch = 0;
        }
        else if ( mRippleField.mPatch )
        {
          do
          {
            patch++;
          } while ( ( patch / 1000 ) * 1000 != patch );
          mLogger.info("applyPV mRippleField.mPatch " + patch);
        }
        else
        {
          patch++;
          mLogger.info("applyPV ripple field default " + patch);
        }
      }
      
      mVersion = String.valueOf(major) + "." + String.valueOf(minor) + ".";
      
      if ( patch < 10 )
      {
        mVersion += "000";
      }
      else if ( patch < 100 )
      {
        mVersion += "00";
      }
      else if ( patch < 1000 )
      {
        mVersion += "0";
      }
      
      mVersion += String.valueOf(patch);
    } while ( exists(releaseManager, rtag_id) );
    
    releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);
  }

  /**returns true if the version exists in the dpkg_archive, deploy_archive or release manager database
   * claims the version in the release manager database
   */
  private boolean exists(ReleaseManager releaseManager, int rtag_id) throws Exception
  {
    mLogger.debug("exists 1 on Package " + mName + " version " + mVersion + " extension " + mExtension);
    boolean retVal = false;
    
    if ( !releaseManager.mUseDatabase )
    {
      mLogger.info("exists 1 !releaseManager.mUseDatabase");
    }
    else
    {
      retVal = exists();

      if ( !retVal )
      {
        String pkg_version = new String(mVersion);
        
        if ( mExtension.length() > 0 )
        {
          pkg_version += mExtension;
        }
        
        retVal = releaseManager.queryPackageVersions(mPid, pkg_version);
      }
    }
    
    mLogger.info("exists 1 returned " + retVal);
    return retVal;
  }

  /**returns true if the version exists in the dpkg_archive or deploy_archive
   */
  boolean exists()
    throws Exception
  {
    mLogger.debug("exists 2 on Package " + mName);
    boolean retVal = false;

    String Release = mGbeDpkg;
    String Deploy = mGbeDply;

    if (Release == null || Deploy == null)
    {
      mLogger.error("exists 2 Release == null || Deploy == null");
      throw new Exception();
    }

    String fs = System.getProperty( "file.separator" );
    String name = new String(Release);
    name += fs + mName + fs + mVersion + mExtension;
    File release = new File(name);

    if (release.exists())
    {
      mLogger.info("exists 2 release.exists()");
      retVal = true;
    }

    if (!retVal && (Release != Deploy))
    {
      name = Deploy + fs + mName + fs + mVersion + mExtension;

      File deploy = new File(name);

      if (deploy.exists())
      {
        mLogger.info("exists 2 deploy.exists()");
        retVal = true;
      }
    }

    mArchivalExistence = retVal;
    mLogger.info("exists 2 returned " + retVal);
    return retVal;
  }

  /**entity class supporting the ERG version numbering standard:
   * <major>.<minor>.<patch/build>
   * patch/build is at least a 4 digit number whose last 3 digits represent the build
   */
  public class VersionNumberingStandard
  {
    /**in terms of the mChangeType Package field,
     * when true indicates the contract of the package has changed in a non backwardly compatible manner
     * in terms of the mRippleField Package field,
     * when true indicates the major version number will be incremented
     * @attribute
     */
    private boolean mMajor = false;

    /**in terms of the mChangeType Package field,
     * when true indicates the contract of the package has changed in a backwardly compatible manner
     * in terms of the mRippleField Package field,
     * when true indicates the minor version number will be incremented
     * @attribute
     */
    private boolean mMinor = false;

    /**in terms of the mChangeType Package field,
     * when true indicates the contract of the package has not changed, but the package has changed internally
     * in terms of the mRippleField Package field,
     * when true indicates the minor version number will be incremented
     * @attribute
     */
    private boolean mPatch = false;

    /**in terms of the mChangeType Package field,
     * when true indicates the package has not changed, its dependencies potentially have
     * in terms of the mRippleField Package field,
     * when true indicates the build number will be incremented
     * @attribute
     */
    private boolean mBuild = true;

    /**constructor
     */
    private VersionNumberingStandard()
    {
      mLogger.debug("VersionNumberingStandard");
    }

    /**sets mBuild true, mMajor false, mMinor false, mPatch false
     */
    void setBuild()
    {
      mLogger.debug("setBuild");
      mBuild = true;
      mMajor = false;
      mMinor = false;
      mPatch = false;
    }

    /**sets mBuild false, mMajor true, mMinor false, mPatch false
     */
    void setMajor()
    {
      mLogger.debug("setMajor");
      mBuild = false;
      mMajor = true;
      mMinor = false;
      mPatch = false;
    }

    /**sets mBuild false, mMajor false, mMinor true, mPatch false
     */
    void setMinor()
    {
      mLogger.debug("setMinor");
      mBuild = false;
      mMajor = false;
      mMinor = true;
      mPatch = false;
    }

    /**sets mBuild false, mMajor false, mMinor false, mPatch true
     */
    void setPatch()
    {
      mLogger.debug("setPatch");
      mBuild = false;
      mMajor = false;
      mMinor = false;
      mPatch = true;
    }

  }

}