Subversion Repositories DevTools

Rev

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