Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
814 mhunt 1
package com.erggroup.buildtool.ripple;
2
 
3
import java.io.File;
4
 
908 mhunt 5
import java.sql.SQLException;
814 mhunt 6
import java.util.Iterator;
7
import java.util.Vector;
8
 
9
import org.apache.log4j.Logger;
10
 
908 mhunt 11
import com.erggroup.buildtool.smtp.Smtpsend;
12
 
814 mhunt 13
public class Package
14
{
15
  /**name of package, must not contain spaces
16
   * @attribute
17
   */
18
  String mName = new String();
19
 
20
  /**package scope
21
   * @attribute
22
   */
23
  String mExtension = new String();
24
 
25
  /**instance identifier
26
   * @attribute
27
   */
28
  String mVersion = new String();
29
 
4212 dpurdie 30
  /** Version string as specified by the user. Used with a ripple
31
   *  type of 'F'
32
   */
33
  String mFixedVersion = new String();
34
 
814 mhunt 35
  /**unique identifier
36
   * for daemon builds = mName + mExtension
37
   * for escrow builds = mName + mVersion + mExtension
38
   * @attribute
39
   */
40
  String mAlias = new String();
41
 
924 dpurdie 42
  /**Version Control System Tag
814 mhunt 43
   * @attribute
44
   */
924 dpurdie 45
  String mVcsTag = new String();
814 mhunt 46
 
47
  /**build standards
48
   * @attribute
49
   */
864 mhunt 50
  Vector<BuildStandard> mBuildStandardCollection = new Vector<BuildStandard>();
814 mhunt 51
 
52
  /**GBE_MACHTYPE used to build generic packages for this baseline
53
   * only has meaning in the daemon build, not the escrow build
54
   * accessed by BuildStandard::getPlatform, getBuildStandard
55
   * @attribute
56
   */
57
  public static final String mGenericMachtype = System.getenv("GBE_MACHTYPE");
58
 
59
  /**build dependencies by package alias
60
   * @attribute
61
   */
864 mhunt 62
  Vector<String> mDependencyCollection = new Vector<String>();
814 mhunt 63
 
64
  /**primary package version key pv_id in database
65
   * @attribute
66
   */
67
  int mId;
68
 
69
  /**indication of the nature of change
70
   * @attribute
71
   */
72
  Package.VersionNumberingStandard mChangeType = new VersionNumberingStandard();
73
 
74
  /**determines what field is rippled on a package version whose dependencies have changed
75
   * @attribute
76
   */
77
  Package.VersionNumberingStandard mRippleField = new VersionNumberingStandard();
78
 
79
  /**interested owners
80
   * @attribute
81
   */
864 mhunt 82
  private Vector<String> mBuildFailureEmailCollection = new Vector<String>();
814 mhunt 83
 
84
  /**when true will trigger unit tests as part of the package build phase in daemon mode
85
   * @attribute
86
   */
87
  boolean mHasAutomatedUnitTests = false;
88
 
89
  /**when true, do not ripple this package through packages which are dependent upon it in daemon mode
90
   * @attribute
91
   */
92
  boolean mAdvisoryRipple = false;
93
 
94
  /**determines the build file the package is built in, or not
95
   *  1 buildfile 1 etc
96
   *  0 not yet processed (initial value)
97
   * -1 not reproducible
98
   * -2 not reproducible on the build platforms configured for this release
99
   * -3 do not ripple
100
   * -4 directly dependent on package versions not in the baseline
101
   * -5 indirectly dependent on package versions which are not reproducible
910 mhunt 102
   *    because of -1, -2 (escrow), -3 (daemon), -4, -6
103
   * -6 circular dependency
814 mhunt 104
   * @attribute
105
   */
106
  int mBuildFile = 0;
107
 
108
  /**build dependencies by package
109
   * @attribute
110
   */
864 mhunt 111
  Vector<Package> mPackageDependencyCollection = new Vector<Package>();
814 mhunt 112
 
113
  /**used for escrow build purposes
114
   * set true when a package has been processed
115
   * @attribute
116
   */
117
  boolean mProcessed = false;
118
 
119
  /**set true for WIP package versions
120
   * only used in daemon mode
121
   * @attribute
122
   */
123
  boolean mDirectlyPlanned = false;
124
 
125
  /**set true when it is determined to be ripple built
126
   * @attribute
127
   */
128
  boolean mIndirectlyPlanned = false;
129
 
908 mhunt 130
  /**non zero instruction number when it is determined to be ripple built by force
131
   * @attribute
132
   */
133
  int mForcedRippleInstruction = 0;
134
 
135
  /**non zero instruction number when it is determined to be test built
136
   * @attribute
137
   */
138
  int mTestBuildInstruction = 0;
139
 
140
  /**test build email destination
141
   * @attribute
142
   */
143
  String mTestBuildEmail;
144
 
924 dpurdie 145
  /**Version Control System Tag
908 mhunt 146
   * @attribute
147
   */
924 dpurdie 148
  String mTestBuildVcsTag = new String();
908 mhunt 149
 
150
  /**build standards
151
   * @attribute
152
   */
153
  Vector<BuildStandard> mTestBuildStandardCollection = new Vector<BuildStandard>();
154
 
155
  /**build dependencies by package alias
156
   * @attribute
157
   */
158
  Vector<String> mTestBuildDependencyCollection = new Vector<String>();
159
 
814 mhunt 160
  /**build dependencies by pv_id (-1 or not used for planned dependencies)
161
   * @attribute
162
   */
864 mhunt 163
  Vector<Integer> mDependencyIDCollection = new Vector<Integer>();
814 mhunt 164
 
165
  /**unique pkg_id in the database
166
   * used for querying package version existence in the database in daemon mode
167
   * @attribute
168
   */
169
  int mPid;
170
 
874 mhunt 171
  /**maximum major number supported for determining ripple number
172
   * @attribute
173
   */
174
  int mMajorLimit;
175
 
176
  /**maximum minor number supported for determining ripple number
177
   * @attribute
178
   */
179
  int mMinorLimit;
180
 
181
  /**maximum patch number supported for determining ripple number
182
   * @attribute
183
   */
184
  int mPatchLimit;
185
 
186
  /**maximum build number number supported for determining ripple number
187
   * @attribute
188
   */
189
  int mBuildLimit;
190
 
814 mhunt 191
  /**Logger
192
   * @attribute
193
   */
194
  private static final Logger mLogger = Logger.getLogger(Package.class);
195
 
196
  /**dpkg archive location
197
   * @attribute
198
   */
199
  public static final String mGbeDpkg = System.getenv("GBE_DPKG");
200
 
896 mhunt 201
  /**Exception message used upon detection an archive does not exist
202
   * Seems this is a rare but transient and recoverable scenario
203
   * @attribute
204
   */
924 dpurdie 205
  public static final String mRecoverable = "dpkg_archive does not exist, recovery will be attempted";
896 mhunt 206
 
924 dpurdie 207
  /**true if the package exists in the package archive (dpkg_archive)
814 mhunt 208
   * @attribute
209
   */
210
  private boolean mArchivalExistence = true;
211
 
852 mhunt 212
  /**when true will trigger source control interaction eg labelling
213
   * @attribute
214
   */
215
  public boolean mRequiresSourceControlInteraction = true;
216
 
910 mhunt 217
  /**when true has been checked for circular dependency
218
   * @attribute
219
   */
220
  boolean mCheckedCircularDependency = false;
221
 
222
  /**when true has circular dependency
223
   * @attribute
224
   */
225
  boolean mHasCircularDependency = false;
226
 
814 mhunt 227
  /**constructor
228
   */
229
  Package(int pv_id, String pkg_name, String v_ext, String alias, 
4212 dpurdie 230
          String pkg_vcs_tag, char change_type, char ripple_field, String pkg_version)
814 mhunt 231
  {
924 dpurdie 232
    mLogger.debug("Package 1: pv_id " + pv_id + " pkg_name " + pkg_name + " v_ext " + v_ext + " alias " + alias + " pkg_vcs_tag " + pkg_vcs_tag + " change_type " + change_type);
814 mhunt 233
    mId = pv_id;
234
    mName = pkg_name;
4219 dpurdie 235
    mVersion = "0.0.0000";
814 mhunt 236
    mExtension = v_ext;
237
    mAlias = alias;
924 dpurdie 238
    mVcsTag = pkg_vcs_tag;
239
 
4212 dpurdie 240
    // Must not have any extension
241
    mFixedVersion = pkg_version;
242
    mFixedVersion = mFixedVersion.substring(0, mFixedVersion.length() - mExtension.length());
243
 
814 mhunt 244
    if (change_type == 'M')
245
    {
902 mhunt 246
      // a ripple_field of 'L' indicates this package has limited version numbering
247
      mChangeType.setMajor(ripple_field == 'L' ? true : false);
814 mhunt 248
    }
249
    else if (change_type == 'N')
250
    {
902 mhunt 251
      mChangeType.setMinor(ripple_field == 'L' ? true : false);
814 mhunt 252
    }
4212 dpurdie 253
    else if (change_type == 'P')
814 mhunt 254
    {
902 mhunt 255
      mChangeType.setPatch(ripple_field == 'L' ? true : false);
814 mhunt 256
    }
4212 dpurdie 257
    else if (change_type == 'F')
258
    {
259
      mChangeType.setFixed();
260
    }
261
    else
262
    {
263
        mChangeType.setUnknown();
264
    }
814 mhunt 265
  }
266
 
267
  /**constructor
268
   */
269
  Package(int pv_id, String pkg_name, String pkg_version, String v_ext, 
924 dpurdie 270
          String alias, String pkg_vcs_tag, char ripple_field)
814 mhunt 271
  {
924 dpurdie 272
    mLogger.debug("Package 2: pv_id " + pv_id + " pkg_name " + pkg_name + " pkg_version " + pkg_version + " v_ext " + v_ext + " alias " + alias + " pkg_vcs_tag " + pkg_vcs_tag + " ripple_field " + ripple_field);
814 mhunt 273
    mId = pv_id;
274
    mName = pkg_name;
275
    mVersion = pkg_version;
276
    int endindex = mVersion.length() - v_ext.length();
277
 
278
    if ( endindex > 0 )
279
    {
280
      mVersion = mVersion.substring(0, endindex);
281
    }
282
 
283
    mExtension = v_ext;
284
    mAlias = alias;
924 dpurdie 285
    mVcsTag = pkg_vcs_tag;
286
 
874 mhunt 287
    // setBuild is the default
814 mhunt 288
    if (ripple_field == 'M')
289
    {
290
      mRippleField.setMajor();
291
    }
292
    else if (ripple_field == 'm')
293
    {
294
      mRippleField.setMinor();
295
    }
296
    else if (ripple_field == 'p')
297
    {
298
      mRippleField.setPatch();
299
    }
874 mhunt 300
    else if (ripple_field == 'L')
301
    {
302
      mRippleField.setLimit();
303
    }
814 mhunt 304
  }
305
 
306
  /**constructor
307
   */
308
  Package()
309
  {
310
    mLogger.debug("Package 3");
311
    mId = 0;
312
    mName = "null";
313
    mExtension = "null";
314
    mAlias = "null";
924 dpurdie 315
    mVcsTag = "null";
814 mhunt 316
  }
317
 
908 mhunt 318
  /**constructor for test build purposes
319
   */
320
  Package(String pkg_name, String v_ext, String alias, 
924 dpurdie 321
          String pkg_vcs_tag, int testBuildInstruction, String email)
908 mhunt 322
  {
924 dpurdie 323
    mLogger.debug("Package 4: pkg_name " + pkg_name + " v_ext " + v_ext + " alias " + alias + " pkg_vcs_tag " + pkg_vcs_tag );
908 mhunt 324
    // don't need pv_id
325
    mId = -1;
326
    mName = pkg_name;
327
    // avoid interaction with real versions
328
    mVersion = "0.0.0000";
329
    mExtension = v_ext;
330
    mAlias = alias;
331
    mTestBuildInstruction = testBuildInstruction;
332
    mTestBuildEmail = email;
924 dpurdie 333
    mTestBuildVcsTag = pkg_vcs_tag;
1320 dpurdie 334
 
908 mhunt 335
  }
336
 
337
/**constructor for unit test purposes
874 mhunt 338
  */
339
  public Package(ReleaseManager rm, String version, int majorLimit, int minorLimit, int patchLimit, int buildNumberLimit)
340
  {
341
    mId = -1;
342
    mRippleField.setLimit();
343
    mVersion = version;
344
    mMajorLimit = majorLimit;
345
    mMinorLimit = minorLimit;
346
    mPatchLimit = patchLimit;
347
    mBuildLimit = buildNumberLimit;
1320 dpurdie 348
 
349
    if ( version.endsWith(".cots") )
350
    {
351
        mExtension = ".cots";
352
        mVersion = version.substring( 0, version.length() - 5 );
353
        mChangeType.setMajor(false);
354
        mChangeType.setMinor(false);
355
        mChangeType.setPatch(true);
356
        mRippleField.setBuild();
357
    }
358
 
874 mhunt 359
    try
360
    {
361
      mId = applyPV( rm, 0 );
362
    }
363
    catch(Exception e)
364
    {
365
    }
366
  }
367
 
368
  /**accessor for unit test purposes
369
   */
370
  public int getId()
371
  {
372
    return mId;
373
  }
374
 
375
  /**accessor for unit test purposes
376
   */
377
  public String getVersion()
378
  {
379
    return mVersion;
380
  }
381
 
814 mhunt 382
  /**returns true if mBuildStandardCollection is not empty
383
   */
384
  boolean isReproducible()
385
  {
386
    mLogger.debug("isReproducible on Package " + mName);
387
    boolean retVal = false;
388
 
389
    if ( mBuildStandardCollection.size() > 0 )
390
    {
391
      retVal = true;
392
    }
393
 
394
    mLogger.info("isReproducible returned " + retVal);
395
    return retVal;
396
  }
397
 
398
  /**returns true if at least one of its BuildStandards has mWin32 or mGeneric true
399
   */
400
  boolean isWin32Built()
401
  {
402
    mLogger.debug("isWin32Built on Package " + mName);
403
    boolean retVal = false;
864 mhunt 404
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 405
    {
864 mhunt 406
      BuildStandard buildStandard = it.next();
814 mhunt 407
 
408
      if (buildStandard.getWin32() || buildStandard.getGeneric())
409
      {
410
        retVal = true;
411
        break;
412
      }
413
    }
414
 
415
    mLogger.info("isWin32Built returned " + retVal);
416
    return retVal;
417
  }
418
 
419
  /**returns true if at least one of its BuildStandards has mSolaris or mGeneric true
420
   */
421
  boolean isSolarisBuilt()
422
  {
423
    mLogger.debug("isSolarisBuilt on Package " + mName);
424
    boolean retVal = false;
864 mhunt 425
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 426
    {
864 mhunt 427
      BuildStandard buildStandard = it.next();
814 mhunt 428
 
429
      if (buildStandard.getSolaris() || buildStandard.getGeneric())
430
      {
431
        retVal = true;
432
        break;
433
      }
434
    }
435
 
436
    mLogger.info("isSolarisBuilt returned " + retVal);
437
    return retVal;
438
  }
439
 
440
  /**returns true if at least one of its BuildStandards has mLinux or mGeneric true
441
   */
442
  boolean isLinuxBuilt()
443
  {
444
    mLogger.debug("isLinuxBuilt on Package " + mName);
445
    boolean retVal = false;
864 mhunt 446
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 447
    {
864 mhunt 448
      BuildStandard buildStandard = it.next();
814 mhunt 449
 
450
      if (buildStandard.getLinux() || buildStandard.getGeneric())
451
      {
452
        retVal = true;
453
        break;
454
      }
455
    }
456
 
457
    mLogger.info("isLinuxBuilt returned " + retVal);
458
    return retVal;
459
  }
460
 
461
  /**returns true if at least one of its BuildStandards has mGeneric true
462
   */
463
  boolean isGeneric()
464
  {
465
    mLogger.debug("isGeneric on Package " + mName);
466
    boolean retVal = false;
864 mhunt 467
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 468
    {
864 mhunt 469
      BuildStandard buildStandard = it.next();
814 mhunt 470
 
471
      if (buildStandard.getGeneric())
472
      {
473
        retVal = true;
474
        break;
475
      }
476
    }
477
 
478
    mLogger.info("isGeneric returned " + retVal);
479
    return retVal;
480
  }
481
 
482
  /**applies the required version number change
874 mhunt 483
   * returns 0 on success
484
   *         1 on cannot work with non standard versioning
485
   *         2 on ripple field limitations prevent a ripple build
4212 dpurdie 486
   *         3 on Invalid Change Type
814 mhunt 487
   */
874 mhunt 488
  int applyPV(ReleaseManager releaseManager, int rtag_id) throws Exception
814 mhunt 489
  {
490
    mLogger.debug("applyPV on Package " + mName);
4212 dpurdie 491
    //
492
    // Four scenarios, only applyPV for 3 of them
493
    //                                  mDirectlyPlanned    mIndirectlyPlanned  mArchivalExistence  mForcedRipple   Action
494
    // WIP/test build exists:           true                true                don't care          don't care     applyPV
495
    // Package version is out of date:  false               true                true                don't care     applyPV
496
    // Forced ripple:                   false               true                don't care          > 0            applyPV
497
    // Package version does not exist:  false               true                false               = 0            do not applyPV
498
    //
908 mhunt 499
    if ( !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence && mForcedRippleInstruction == 0 )
814 mhunt 500
    {
501
      // the package has an mIndirectlyPlanned flag set true in daemon mode because the package does not exist in an archive
502
      // do not apply a different package version
908 mhunt 503
      mLogger.info("applyPV !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence && zero mForcedRippleInstruction on Package " + mName);
836 mhunt 504
      releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);
874 mhunt 505
      mLogger.info("applyPv returned 0");
506
      return 0;
814 mhunt 507
    }
908 mhunt 508
 
509
    // override - no longer doing a rebuild - version number change from this point on
510
    if ( mTestBuildInstruction == 0 )
511
    {
512
      mRequiresSourceControlInteraction = true;
513
    }
4212 dpurdie 514
 
515
    //
516
    //  Detect invalid change type
517
    //  Flagged when package instance is created
518
    //
519
    if (mChangeType.mUnknown)
520
    {
521
        mLogger.info("Package Vesrion specified on Package " + mName + "New Version:" + mVersion);
522
        mLogger.info("applyPv returned 3");
523
        return 3;
524
    }
814 mhunt 525
 
4212 dpurdie 526
    // If we are not calculating the new package version because the user has fixed the version
527
    // of the package. We are given the new package version.
528
    if (mChangeType.mFixed)
529
    {
530
        // mVersion is already setup
531
 
532
        mVersion = mFixedVersion;
533
        mLogger.info("Package Vesrion specified on Package " + mName + "New Version:" + mVersion);
534
        releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);
535
        mLogger.info("applyPv returned 0");
536
        return 0;
537
    }
538
 
539
    // We need to calculate the new version number
540
    //
892 mhunt 541
    MutableInt major = new MutableInt();
542
    major.value = 0;
543
    MutableInt minor = new MutableInt();
544
    minor.value = 0;
545
    MutableInt patch = new MutableInt();
546
    patch.value = 1000;
814 mhunt 547
 
548
    String field[] = mVersion.split("\\D");
888 mhunt 549
    String nonStandardCotsVersion = "";
550
 
814 mhunt 551
    if ( field.length == 3 )
552
    {
892 mhunt 553
      major.value = Integer.parseInt(field[0]);
554
      minor.value = Integer.parseInt(field[1]);
555
      patch.value = Integer.parseInt(field[2]);
814 mhunt 556
    }
557
    else
558
    {
1320 dpurdie 559
      //
560
      //    Can ripple a .cots package under very controlled conditions
561
      //    Its ends with a .patchBuild field
4212 dpurdie 562
      //    Package is marked as ripple via build number
563
      //    Change type of Major and Minor are not allowed
1320 dpurdie 564
      //
888 mhunt 565
      if ( !mChangeType.mMajor &&
566
           !mChangeType.mMinor &&
567
           mRippleField.mBuild &&
568
           mExtension.compareTo(".cots") == 0 &&
569
           field.length > 0 )
570
      {
571
        // DEVI 52782
572
        // allow and work with (ripple build) versions a.b.c.d....xxxx
573
        // where xxxx.length > 3
574
        String patchStr = field[field.length - 1];
575
        int patchLen = patchStr.length();
1320 dpurdie 576
 
888 mhunt 577
        // check patchStr is the last (at least 4) digits
578
        if ( patchLen > 3 && mVersion.substring( mVersion.length() - patchLen, mVersion.length() ).compareTo(patchStr) == 0 )
579
        {
892 mhunt 580
          patch.value = Integer.parseInt(patchStr);
888 mhunt 581
          nonStandardCotsVersion = mVersion.substring(0, mVersion.length() - patchLen );
582
        }
583
      }
584
 
585
      if ( nonStandardCotsVersion.length() == 0 )
586
      {
587
        // cannot work with non standard versioning
588
        mLogger.error("applyPV cannot work with non standard versioning");
589
        mLogger.info("applyPv returned 1");
590
        return 1;
591
      }
814 mhunt 592
    }
593
 
888 mhunt 594
    if ( nonStandardCotsVersion.length() == 0 &&
892 mhunt 595
         patch.value < 1000 && 
888 mhunt 596
         field[2].substring(0, 1).compareTo("0") != 0 )
814 mhunt 597
    {
598
      mLogger.info("applyPV accomodate old style mVersion of the form 1.0.1");
892 mhunt 599
      patch.value = patch.value * 1000;
814 mhunt 600
    }
601
 
602
    // mChangeType overrides mRippleField
603
    do
604
    {
605
      if ( mChangeType.mMajor )
606
      {
892 mhunt 607
        if ( !incrementFieldsAccordingToLimits(4, major, minor, patch) )
608
        {
609
          mLogger.info("applyPv returned 2");
610
          return 2;
611
        }
814 mhunt 612
      }
613
      else if ( mChangeType.mMinor )
614
      {
892 mhunt 615
        if ( !incrementFieldsAccordingToLimits(3, major, minor, patch) )
616
        {
617
          mLogger.info("applyPv returned 2");
618
          return 2;
619
        }
814 mhunt 620
      }
621
      else if ( mChangeType.mPatch )
622
      {
892 mhunt 623
        if ( !incrementFieldsAccordingToLimits(2, major, minor, patch) )
814 mhunt 624
        {
892 mhunt 625
          mLogger.info("applyPv returned 2");
626
          return 2;
627
        }
814 mhunt 628
      }
629
      else
630
      {
631
        if ( mRippleField.mMajor )
632
        {
892 mhunt 633
          major.value++;
634
          mLogger.info("applyPV mRippleField.mMajor " + major.value);
635
          minor.value = 0;
636
          patch.value = 0;
814 mhunt 637
        }
638
        else if ( mRippleField.mMinor )
639
        {
892 mhunt 640
          minor.value++;
641
          mLogger.info("applyPV mRippleField.mMinor " + minor.value);
642
          patch.value = 0;
814 mhunt 643
        }
644
        else if ( mRippleField.mPatch )
645
        {
646
          do
647
          {
892 mhunt 648
            patch.value++;
649
          } while ( ( patch.value / 1000 ) * 1000 != patch.value );
650
          mLogger.info("applyPV mRippleField.mPatch " + patch.value);
814 mhunt 651
        }
874 mhunt 652
        else if ( mRippleField.mBuild )
814 mhunt 653
        {
892 mhunt 654
          patch.value++;
655
          mLogger.info("applyPV mRippleField.mBuild " + patch.value);
814 mhunt 656
        }
874 mhunt 657
        else
658
        {
892 mhunt 659
          if ( !incrementFieldsAccordingToLimits(1, major, minor, patch) )
874 mhunt 660
          {
661
            mLogger.info("applyPv returned 2");
662
            return 2;
663
          }
664
        }
814 mhunt 665
      }
888 mhunt 666
 
667
      if ( nonStandardCotsVersion.length() == 0 )
668
      {
892 mhunt 669
        mVersion = String.valueOf(major.value) + "." + String.valueOf(minor.value) + ".";
888 mhunt 670
      }
671
      else
672
      {
673
        mVersion = nonStandardCotsVersion;
674
      }
814 mhunt 675
 
892 mhunt 676
      if ( patch.value < 10 )
814 mhunt 677
      {
678
        mVersion += "000";
679
      }
892 mhunt 680
      else if ( patch.value < 100 )
814 mhunt 681
      {
682
        mVersion += "00";
683
      }
892 mhunt 684
      else if ( patch.value < 1000 )
814 mhunt 685
      {
686
        mVersion += "0";
687
      }
688
 
892 mhunt 689
      mVersion += String.valueOf(patch.value);
814 mhunt 690
    } while ( exists(releaseManager, rtag_id) );
691
 
692
    releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);
874 mhunt 693
    mLogger.info("applyPv returned 0");
694
    return 0;
814 mhunt 695
  }
696
 
892 mhunt 697
  /**increments fields according to mRippleField.mLimit if necessary
698
   * will apply it to the field passed as follows
699
   * 1 = build
700
   * 2 = patch
701
   * 3 = minor
702
   * other = major
703
   * returns true on success
704
   *         false on ripple field limitations prevent a ripple build
705
   */
706
  private boolean incrementFieldsAccordingToLimits(int field, MutableInt major, MutableInt minor, MutableInt patch)
707
  {
708
    boolean retVal = true;
709
 
902 mhunt 710
    if (!mChangeType.mLimit && !mRippleField.mLimit)
892 mhunt 711
    {
712
      // simple case
713
      // no need to take field limits into consideration
714
      switch (field)
715
      {
716
      case 1:
717
        // unreachable
718
        // the only scenario involving build number manipulation involves the mRippleField.mLimit being set
719
        retVal = false;
720
        break;
721
      case 2:
722
        do
723
        {
724
          patch.value++;
725
        } while ( ( patch.value / 1000 ) * 1000 != patch.value );
726
        mLogger.info("incrementFieldsAccordingToLimits patch " + patch.value);
727
        break;
728
      case 3:
729
        minor.value++;
730
        mLogger.info("incrementFieldsAccordingToLimits minor " + minor.value);
731
        patch.value = 0;
732
        break;
733
      default:
734
        major.value++;
735
        mLogger.info("incrementFieldsAccordingToLimits major " + major.value);
736
        minor.value = 0;
737
        patch.value = 0;
738
      }
739
    }
740
    else
741
    {
742
      // take field limits into consideration
743
      boolean changeOccurred = false;
744
      boolean incrementField = true;
745
 
746
      switch (field)
747
      {
748
      case 1:
749
        if ( mBuildLimit != 0 )
750
        {
751
          // increment or reset the patch build number
752
          int buildNumber = patch.value - (patch.value/1000) * 1000;
753
 
754
          if ( buildNumber < mBuildLimit )
755
          {
756
            // can increment the patch build number
757
            patch.value++;
758
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit build number " + patch.value);
759
            changeOccurred = true;
760
            incrementField = false;
761
          }
762
          else
763
          {
764
            if ( mPatchLimit == 0 )
765
            {
766
              // reset the patch number and patch build number
767
              patch.value = 0;
768
            }
769
          }
770
        }
771
        // no break by design
772
      case 2:
773
        if ( mPatchLimit != 0 && incrementField )
774
        {
775
          // increment or reset the patch number
776
          if ( ( patch.value / 1000 ) < mPatchLimit )
777
          {
778
            do
779
            {
780
              patch.value++;
781
            } while ( ( patch.value / 1000 ) * 1000 != patch.value );
782
 
783
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit patch " + patch.value);
784
            changeOccurred = true;
785
            incrementField = false;
786
          }
787
          else
788
          {
789
            // reset the patch number and patch build number
790
            patch.value = 0;
791
          }
792
        }
793
        // no break by design
794
      case 3:
795
        if ( mMinorLimit != 0 && incrementField )
796
        {
797
          // increment or reset the minor number
798
          if ( minor.value < mMinorLimit )
799
          {
800
            minor.value++;
801
            patch.value = 0;
802
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit minor " + minor.value);
803
            changeOccurred = true;
804
            incrementField = false;
805
          }
806
          else
807
          {
808
            // reset the minor number
809
            minor.value = 0;
810
          }
811
        }
812
        // no break by design
813
      default:
814
        if ( mMajorLimit != 0 && incrementField )
815
        {
816
          // increment or reset the major number
817
          if ( major.value < mMajorLimit )
818
          {
819
            // increment the major number
820
            changeOccurred = true;
821
            major.value++;
822
            minor.value = 0;
823
            patch.value = 0;
824
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit major " + major.value);
825
          }
826
        }
827
      }
828
 
829
      if ( !changeOccurred )
830
      {
831
        // unable to increment a field due to field limitations
832
        mLogger.error("incrementFieldsAccordingToLimits ripple field limitations prevent a ripple build");
833
        mLogger.info("incrementFieldsAccordingToLimits returned false");
834
        retVal = false;
835
      }
836
    }
837
 
838
    return retVal;
839
  }
840
 
924 dpurdie 841
  /**returns true if the version exists in the dpkg_archive or release manager database
814 mhunt 842
   * claims the version in the release manager database
843
   */
844
  private boolean exists(ReleaseManager releaseManager, int rtag_id) throws Exception
845
  {
846
    mLogger.debug("exists 1 on Package " + mName + " version " + mVersion + " extension " + mExtension);
847
    boolean retVal = false;
848
 
864 mhunt 849
    if ( !ReleaseManager.mUseDatabase )
814 mhunt 850
    {
851
      mLogger.info("exists 1 !releaseManager.mUseDatabase");
852
    }
853
    else
854
    {
855
      retVal = exists();
856
 
857
      if ( !retVal )
858
      {
859
        String pkg_version = new String(mVersion);
860
 
861
        if ( mExtension.length() > 0 )
862
        {
863
          pkg_version += mExtension;
864
        }
865
 
866
        retVal = releaseManager.queryPackageVersions(mPid, pkg_version);
867
      }
868
    }
869
 
870
    mLogger.info("exists 1 returned " + retVal);
871
    return retVal;
872
  }
873
 
924 dpurdie 874
  /**returns true if the required package archives (dpkg_archive) exist
896 mhunt 875
   * attempt to recover from their transient loss 
876
   */
877
  public static boolean recover()
878
  {
879
    mLogger.debug("recover");
880
    boolean retVal = false;
881
 
882
    String Release = mGbeDpkg;
924 dpurdie 883
    if (Release != null )
896 mhunt 884
    {
885
      File dpkg = new File(mGbeDpkg);
886
 
924 dpurdie 887
      if ( dpkg.exists() )
896 mhunt 888
      {
889
        retVal = true;
4123 dpurdie 890
        mLogger.fatal("recover: dpkg_archive access has been restored");
896 mhunt 891
      }
892
    }
893
 
894
    mLogger.info("recover returned " + retVal);
895
    return retVal;
896
  }
897
 
924 dpurdie 898
  /**returns true if the version exists in a package archive (dpkg_archive)
814 mhunt 899
   */
900
  boolean exists()
901
    throws Exception
902
  {
903
    mLogger.debug("exists 2 on Package " + mName);
904
    boolean retVal = false;
905
 
906
    String Release = mGbeDpkg;
924 dpurdie 907
    if (Release == null)
814 mhunt 908
    {
924 dpurdie 909
      mLogger.fatal("exists 2 Release == null");
910
      throw new Exception("exists 2 Release == null");
814 mhunt 911
    }
896 mhunt 912
 
913
    File dpkg = new File(mGbeDpkg);
924 dpurdie 914
    if ( !dpkg.exists()  )
896 mhunt 915
    {
916
      mLogger.fatal("exists 2 " + mRecoverable);
917
      throw new Exception(mRecoverable);
918
    }
814 mhunt 919
 
920
    String fs = System.getProperty( "file.separator" );
921
    String name = new String(Release);
922
    name += fs + mName + fs + mVersion + mExtension;
923
    File release = new File(name);
924
 
925
    if (release.exists())
926
    {
927
      mLogger.info("exists 2 release.exists()");
928
      retVal = true;
929
    }
930
 
931
    mArchivalExistence = retVal;
932
    mLogger.info("exists 2 returned " + retVal);
933
    return retVal;
934
  }
854 mhunt 935
 
936
  /**returns email information
937
   */
938
  String emailInfo( String lf )
939
  {
940
    String retVal = new String();
941
 
864 mhunt 942
    for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); )
854 mhunt 943
    {
864 mhunt 944
      String email = it.next();
854 mhunt 945
      retVal +=
946
      "  <owner email=\"" + email +"\"/>" + lf;
947
    }
948
 
949
    return retVal;
950
  }
814 mhunt 951
 
866 mhunt 952
  /**returns email information
953
   */
954
  String emailInfoNonAntTask()
955
  {
956
    String retVal = null;
957
 
958
    for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); )
959
    {
960
      String email = it.next();
961
 
962
      if ( retVal == null )
963
      {
964
        retVal = new String();
965
      }
966
      else
967
      {
968
        retVal += ",";
969
      }
970
      retVal += email;
971
    }
972
 
973
    return retVal;
974
  }
975
 
864 mhunt 976
  /**adds email to mBuildFailureEmailCollection if unique
977
   */
978
  void addEmail( String email )
979
  {
980
    boolean alreadyExists = false;
981
 
982
    for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); )
983
    {
984
      String existingEmail = it.next();
985
 
986
      if ( existingEmail.compareTo(email) == 0 )
987
      {
988
        alreadyExists = true;
989
        break;
990
      }
991
    }
992
 
993
    if ( !alreadyExists )
994
    {
995
      mBuildFailureEmailCollection.add(email);
996
    }
997
  }
998
 
908 mhunt 999
  /**accessor method
1000
   */
1001
  void setEmail()
1002
  {
1003
    mBuildFailureEmailCollection.clear();
1004
    addEmail( mTestBuildEmail );
1005
  }
1006
 
1007
  /**accessor method
1008
   */
1009
  void setDependencyCollection()
1010
  {
1011
    // does not worry about mPackageDendencyCollection by design
1012
    mDependencyCollection.clear();
1013
 
1014
    for (Iterator<String> it = mTestBuildDependencyCollection.iterator(); it.hasNext(); )
1015
    {
1016
      String dependency = it.next();
1017
      mDependencyCollection.add(dependency);
1018
    }
1019
  }
1020
 
1021
  /**accessor method
1022
   */
1023
  void setBuildStandardCollection()
1024
  {
1025
    mBuildStandardCollection.clear();
1026
 
1027
    for (Iterator<BuildStandard> it = mTestBuildStandardCollection.iterator(); it.hasNext(); )
1028
    {
1029
      BuildStandard buildStandard = it.next();
1030
      mBuildStandardCollection.add(buildStandard);
1031
    }
1032
  }
1033
 
1034
  /**sends email notification and marks the instruction complete in the database
1035
   */
1036
  public void completeTestBuild( String mailServer, String mailSender, ReleaseManager releaseManager, String release, boolean success ) throws SQLException, Exception
1037
  {
1038
    mLogger.debug("completeTestBuild");
1039
 
1040
    if ( mTestBuildInstruction == 0)
1041
    {
4123 dpurdie 1042
      mLogger.fatal("completeTestBuild. Not Build Instruction");
908 mhunt 1043
      return;
1044
    }
4201 dpurdie 1045
    String subject = (success == true ? "TEST BUILD COMPLETED SUCCESSFULLY" : "TEST BUILD FAILED") + " on package " + mAlias; 
908 mhunt 1046
    String mailBody="Test build issues are identified in preceding build failure email.<p>" +
1047
                    "Release: " + release + "<br>" +
1048
                    "Package: " + mAlias + "<br>" +
924 dpurdie 1049
                    "VcsTag: " + mVcsTag + "<br>" +
1050
                    "Build dependencies:<br>";
4201 dpurdie 1051
    String indentString = "&nbsp;&nbsp;&nbsp;&nbsp;";
908 mhunt 1052
 
1053
    for (Iterator<Package> it3 = mPackageDependencyCollection.iterator(); it3.hasNext(); )
1054
    {
1055
      Package depend = it3.next();
1056
 
1057
      String dependsExtension = depend.mExtension;
1058
      String dependsVersion = depend.mVersion;
1059
 
1060
      if ( dependsExtension.length() > 0 )
1061
      {
1062
        dependsVersion += dependsExtension;
1063
      }
924 dpurdie 1064
      mailBody += indentString + "\'" + depend.mName + "\',\'" + dependsVersion + "\' <br>";
908 mhunt 1065
    }
1066
 
924 dpurdie 1067
    mailBody += "<br>Build standards:<br>";
908 mhunt 1068
 
1069
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
1070
    {
1071
      BuildStandard bs = it.next();
1072
 
1073
      String platform = bs.getPlatform(!ReleaseManager.mUseDatabase, false);
1074
 
1075
      if ( platform.length() > 0 )
1076
      {
924 dpurdie 1077
        mailBody += indentString + platform + ", ";
908 mhunt 1078
      }
1079
 
1080
      String standard = bs.getBuildStandard(!ReleaseManager.mUseDatabase, false);
1081
 
1082
      if ( standard.length() > 0 )
1083
      {
1084
        mailBody += standard + "<br>";
1085
      }
1086
    }
924 dpurdie 1087
 
1088
    mailBody += "<p><hr>";
908 mhunt 1089
    try
1090
    {
4123 dpurdie 1091
      String target = emailInfoNonAntTask();
1092
mLogger.fatal("completeTestBuildEmail Server: " + mailServer);
1093
mLogger.fatal("completeTestBuildEmail Sender: " + mailSender);
1094
mLogger.fatal("completeTestBuildEmail Target: " + target);
1095
 
908 mhunt 1096
      Smtpsend.send(
924 dpurdie 1097
      mailServer,           // mailServer
1098
      mailSender,           // source
4123 dpurdie 1099
      target,               // target
1100
      mailSender,           // cc
924 dpurdie 1101
      null,                 // bcc
4201 dpurdie 1102
      subject,              // subject
924 dpurdie 1103
      mailBody,             // body
1104
      null                  // attachment
908 mhunt 1105
      );
1106
    }
1107
    catch( Exception e )
1108
    {
4123 dpurdie 1109
        mLogger.warn("Email Failure: completeTestBuild:" + e.getMessage());
908 mhunt 1110
    }
1111
 
1112
    releaseManager.markDaemonInstCompletedConnect(mTestBuildInstruction);
4123 dpurdie 1113
mLogger.fatal("completeTest. Returning");
908 mhunt 1114
  }
1115
 
910 mhunt 1116
  /**returns true if the package has a circular dependency
1117
   */
1118
  public boolean hasCircularDependency(RippleEngine ripEng)
1119
  {
1120
    mLogger.debug("hasCircularDependency");
1121
    boolean retVal = detectCircularDependency( mAlias, ripEng );
1122
    mLogger.info("hasCircularDependency returned " + retVal);
1123
    return retVal;
1124
  }
1125
 
1126
  /**returns true if the package has a circular dependency
1127
   */
1128
  public boolean detectCircularDependency(String alias, RippleEngine ripEng)
1129
  {
1130
    mLogger.debug("detectCircularDependency");
1131
    boolean retVal = false;
1132
 
1133
    // if this package has yet to be checked for circular dependency
1134
    if ( !mCheckedCircularDependency )
1135
    {
1136
      for (Iterator<String> it2 = mDependencyCollection.iterator(); it2.hasNext(); )
1137
      {
1138
        String dependencyAlias = it2.next();
1139
 
1140
        // check its direct dependencies for an alias match
1141
        if ( alias.compareTo( dependencyAlias ) == 0 )
1142
        {
1143
          retVal = true;
1144
          break;
1145
        }
1146
 
1147
        Package dependency = ripEng.findPackage( dependencyAlias );
1148
 
1149
        // check its indirect dependencies for an alias match
1150
        if ( dependency.detectCircularDependency(alias, ripEng) )
1151
        {
1152
          retVal = true;
1153
          break;
1154
        }
1155
      }
1156
      // mark the check complete
1157
      mCheckedCircularDependency = true;
1158
      // persist the circular dependency outcome
1159
      mHasCircularDependency = retVal;
1160
    }
1161
    else
1162
    {
1163
      // return the persisted circular dependency outcome
1164
      retVal = mHasCircularDependency;
1165
    }
1166
    mLogger.info("detectCircularDependency 2 returned " + retVal);
1167
    return retVal;
1168
  }
1169
 
814 mhunt 1170
  /**entity class supporting the ERG version numbering standard:
1171
   * <major>.<minor>.<patch/build>
1172
   * patch/build is at least a 4 digit number whose last 3 digits represent the build
1173
   */
1174
  public class VersionNumberingStandard
1175
  {
1176
    /**in terms of the mChangeType Package field,
1177
     * when true indicates the contract of the package has changed in a non backwardly compatible manner
1178
     * in terms of the mRippleField Package field,
1179
     * when true indicates the major version number will be incremented
1180
     * @attribute
1181
     */
1182
    private boolean mMajor = false;
1183
 
1184
    /**in terms of the mChangeType Package field,
1185
     * when true indicates the contract of the package has changed in a backwardly compatible manner
1186
     * in terms of the mRippleField Package field,
1187
     * when true indicates the minor version number will be incremented
1188
     * @attribute
1189
     */
1190
    private boolean mMinor = false;
1191
 
1192
    /**in terms of the mChangeType Package field,
1193
     * when true indicates the contract of the package has not changed, but the package has changed internally
1194
     * in terms of the mRippleField Package field,
1195
     * when true indicates the minor version number will be incremented
1196
     * @attribute
1197
     */
1198
    private boolean mPatch = false;
1199
 
1200
    /**in terms of the mChangeType Package field,
1201
     * when true indicates the package has not changed, its dependencies potentially have
1202
     * in terms of the mRippleField Package field,
1203
     * when true indicates the build number will be incremented
1204
     * @attribute
1205
     */
1206
    private boolean mBuild = true;
1207
 
874 mhunt 1208
    /**in terms of the mChangeType Package field,
902 mhunt 1209
     * when true indicates the major, minor, and patch number will be incremented according to field limits
874 mhunt 1210
     * in terms of the mRippleField Package field,
1211
     * when true indicates the major, minor, patch and build number will be incremented according to field limits
1212
     * @attribute
1213
     */
1214
    private boolean mLimit = false;
1215
 
4212 dpurdie 1216
    /**in terms of the mChangeType Package field,
1217
     * when true indicates the package version number will not be rippled. The user will have 
1218
     * fixed the version number. This is only application to WIP packages 
1219
     *  
1220
     * @attribute
1221
     */
1222
    private boolean mFixed = false;
1223
 
1224
    /**in terms of the mChangeType Package field,
1225
     * when true indicates the method of rippling a package version 
1226
     * number is not known. 
1227
     *  
1228
     * @attribute
1229
     */
1230
    private boolean mUnknown = false;
1231
 
814 mhunt 1232
    /**constructor
1233
     */
1234
    private VersionNumberingStandard()
1235
    {
1236
      mLogger.debug("VersionNumberingStandard");
1237
    }
1238
 
874 mhunt 1239
    /**sets mBuild true, mMajor false, mMinor false, mPatch false, mLimit false
814 mhunt 1240
     */
1241
    void setBuild()
1242
    {
1243
      mLogger.debug("setBuild");
1244
      mBuild = true;
1245
      mMajor = false;
1246
      mMinor = false;
1247
      mPatch = false;
874 mhunt 1248
      mLimit = false;
4212 dpurdie 1249
      mFixed = false;
814 mhunt 1250
    }
1251
 
874 mhunt 1252
    /**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit false
814 mhunt 1253
     */
1254
    void setMajor()
1255
    {
1256
      mLogger.debug("setMajor");
1257
      mBuild = false;
1258
      mMajor = true;
1259
      mMinor = false;
1260
      mPatch = false;
874 mhunt 1261
      mLimit = false;
4212 dpurdie 1262
      mFixed = false;
814 mhunt 1263
    }
1264
 
902 mhunt 1265
    /**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit limit
1266
     */
1267
    void setMajor( boolean limit )
1268
    {
1269
      mLogger.debug("setMajor " + limit);
1270
      mBuild = false;
1271
      mMajor = true;
1272
      mMinor = false;
1273
      mPatch = false;
1274
      mLimit = limit;
4212 dpurdie 1275
      mFixed = false;
902 mhunt 1276
    }
1277
 
874 mhunt 1278
    /**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit false
814 mhunt 1279
     */
1280
    void setMinor()
1281
    {
1282
      mLogger.debug("setMinor");
1283
      mBuild = false;
1284
      mMajor = false;
1285
      mMinor = true;
1286
      mPatch = false;
874 mhunt 1287
      mLimit = false;
4212 dpurdie 1288
      mFixed = false;
814 mhunt 1289
    }
1290
 
902 mhunt 1291
    /**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit limit
1292
     */
1293
    void setMinor( boolean limit )
1294
    {
1295
      mLogger.debug("setMinor " + limit);
1296
      mBuild = false;
1297
      mMajor = false;
1298
      mMinor = true;
1299
      mPatch = false;
1300
      mLimit = limit;
4212 dpurdie 1301
      mFixed = false;
902 mhunt 1302
    }
1303
 
874 mhunt 1304
    /**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit false
814 mhunt 1305
     */
1306
    void setPatch()
1307
    {
1308
      mLogger.debug("setPatch");
1309
      mBuild = false;
1310
      mMajor = false;
1311
      mMinor = false;
1312
      mPatch = true;
874 mhunt 1313
      mLimit = false;
4212 dpurdie 1314
      mFixed = false;
814 mhunt 1315
    }
1316
 
902 mhunt 1317
    /**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit limit
1318
     */
1319
    void setPatch( boolean limit )
1320
    {
1321
      mLogger.debug("setPatch");
1322
      mBuild = false;
1323
      mMajor = false;
1324
      mMinor = false;
1325
      mPatch = true;
1326
      mLimit = limit;
4212 dpurdie 1327
      mFixed = false;
902 mhunt 1328
    }
1329
 
874 mhunt 1330
    /**sets mBuild false, mMajor false, mMinor false, mPatch false, mLimit true
1331
     */
1332
    void setLimit()
1333
    {
1334
      mLogger.debug("setPatch");
1335
      mBuild = false;
1336
      mMajor = false;
1337
      mMinor = false;
1338
      mPatch = false;
1339
      mLimit = true;
4212 dpurdie 1340
      mFixed = false;
874 mhunt 1341
    }
1342
 
4212 dpurdie 1343
    /**sets parameters to indicate that the change type is Fixed. The version number is set by the user 
1344
     * and a ripple will not be calculated 
1345
     */ 
1346
    void setFixed()
1347
    {
1348
        mLogger.debug("setFixed");
1349
        mBuild = false;
1350
        mMajor = false;
1351
        mMinor = false;
1352
        mPatch = false;
1353
        mLimit = false;
1354
        mFixed = true;
1355
    }
1356
 
1357
    /** Sets parameters to indicate that the chnage type is not
1358
     *  known
1359
     *  
1360
     */
1361
    void setUnknown()
1362
    {
1363
        mUnknown = true;
1364
    }
1365
 
814 mhunt 1366
  }
1367
 
1368
}