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