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