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
    }
924 dpurdie 998
    String indentString = "&nbsp;&nbsp;&nbsp;&nbsp;";
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>";
908 mhunt 1004
 
1005
    for (Iterator<Package> it3 = mPackageDependencyCollection.iterator(); it3.hasNext(); )
1006
    {
1007
      Package depend = it3.next();
1008
 
1009
      String dependsExtension = depend.mExtension;
1010
      String dependsVersion = depend.mVersion;
1011
 
1012
      if ( dependsExtension.length() > 0 )
1013
      {
1014
        dependsVersion += dependsExtension;
1015
      }
924 dpurdie 1016
      mailBody += indentString + "\'" + depend.mName + "\',\'" + dependsVersion + "\' <br>";
908 mhunt 1017
    }
1018
 
924 dpurdie 1019
    mailBody += "<br>Build standards:<br>";
908 mhunt 1020
 
1021
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
1022
    {
1023
      BuildStandard bs = it.next();
1024
 
1025
      String platform = bs.getPlatform(!ReleaseManager.mUseDatabase, false);
1026
 
1027
      if ( platform.length() > 0 )
1028
      {
924 dpurdie 1029
        mailBody += indentString + platform + ", ";
908 mhunt 1030
      }
1031
 
1032
      String standard = bs.getBuildStandard(!ReleaseManager.mUseDatabase, false);
1033
 
1034
      if ( standard.length() > 0 )
1035
      {
1036
        mailBody += standard + "<br>";
1037
      }
1038
    }
924 dpurdie 1039
 
1040
    mailBody += "<p><hr>";
908 mhunt 1041
    try
1042
    {
4123 dpurdie 1043
      String target = emailInfoNonAntTask();
1044
mLogger.fatal("completeTestBuildEmail Server: " + mailServer);
1045
mLogger.fatal("completeTestBuildEmail Sender: " + mailSender);
1046
mLogger.fatal("completeTestBuildEmail Target: " + target);
1047
 
908 mhunt 1048
      Smtpsend.send(
924 dpurdie 1049
      mailServer,           // mailServer
1050
      mailSender,           // source
4123 dpurdie 1051
      target,               // target
1052
      mailSender,           // cc
924 dpurdie 1053
      null,                 // bcc
908 mhunt 1054
      success == true ? "TEST BUILD COMPLETED SUCCESSFULLY" : "TEST BUILD FAILED", // subject
924 dpurdie 1055
      mailBody,             // body
1056
      null                  // attachment
908 mhunt 1057
      );
1058
    }
1059
    catch( Exception e )
1060
    {
4123 dpurdie 1061
        mLogger.warn("Email Failure: completeTestBuild:" + e.getMessage());
908 mhunt 1062
    }
1063
 
1064
    releaseManager.markDaemonInstCompletedConnect(mTestBuildInstruction);
4123 dpurdie 1065
mLogger.fatal("completeTest. Returning");
908 mhunt 1066
  }
1067
 
910 mhunt 1068
  /**returns true if the package has a circular dependency
1069
   */
1070
  public boolean hasCircularDependency(RippleEngine ripEng)
1071
  {
1072
    mLogger.debug("hasCircularDependency");
1073
    boolean retVal = detectCircularDependency( mAlias, ripEng );
1074
    mLogger.info("hasCircularDependency returned " + retVal);
1075
    return retVal;
1076
  }
1077
 
1078
  /**returns true if the package has a circular dependency
1079
   */
1080
  public boolean detectCircularDependency(String alias, RippleEngine ripEng)
1081
  {
1082
    mLogger.debug("detectCircularDependency");
1083
    boolean retVal = false;
1084
 
1085
    // if this package has yet to be checked for circular dependency
1086
    if ( !mCheckedCircularDependency )
1087
    {
1088
      for (Iterator<String> it2 = mDependencyCollection.iterator(); it2.hasNext(); )
1089
      {
1090
        String dependencyAlias = it2.next();
1091
 
1092
        // check its direct dependencies for an alias match
1093
        if ( alias.compareTo( dependencyAlias ) == 0 )
1094
        {
1095
          retVal = true;
1096
          break;
1097
        }
1098
 
1099
        Package dependency = ripEng.findPackage( dependencyAlias );
1100
 
1101
        // check its indirect dependencies for an alias match
1102
        if ( dependency.detectCircularDependency(alias, ripEng) )
1103
        {
1104
          retVal = true;
1105
          break;
1106
        }
1107
      }
1108
      // mark the check complete
1109
      mCheckedCircularDependency = true;
1110
      // persist the circular dependency outcome
1111
      mHasCircularDependency = retVal;
1112
    }
1113
    else
1114
    {
1115
      // return the persisted circular dependency outcome
1116
      retVal = mHasCircularDependency;
1117
    }
1118
    mLogger.info("detectCircularDependency 2 returned " + retVal);
1119
    return retVal;
1120
  }
1121
 
814 mhunt 1122
  /**entity class supporting the ERG version numbering standard:
1123
   * <major>.<minor>.<patch/build>
1124
   * patch/build is at least a 4 digit number whose last 3 digits represent the build
1125
   */
1126
  public class VersionNumberingStandard
1127
  {
1128
    /**in terms of the mChangeType Package field,
1129
     * when true indicates the contract of the package has changed in a non backwardly compatible manner
1130
     * in terms of the mRippleField Package field,
1131
     * when true indicates the major version number will be incremented
1132
     * @attribute
1133
     */
1134
    private boolean mMajor = false;
1135
 
1136
    /**in terms of the mChangeType Package field,
1137
     * when true indicates the contract of the package has changed in a backwardly compatible manner
1138
     * in terms of the mRippleField Package field,
1139
     * when true indicates the minor version number will be incremented
1140
     * @attribute
1141
     */
1142
    private boolean mMinor = false;
1143
 
1144
    /**in terms of the mChangeType Package field,
1145
     * when true indicates the contract of the package has not changed, but the package has changed internally
1146
     * in terms of the mRippleField Package field,
1147
     * when true indicates the minor version number will be incremented
1148
     * @attribute
1149
     */
1150
    private boolean mPatch = false;
1151
 
1152
    /**in terms of the mChangeType Package field,
1153
     * when true indicates the package has not changed, its dependencies potentially have
1154
     * in terms of the mRippleField Package field,
1155
     * when true indicates the build number will be incremented
1156
     * @attribute
1157
     */
1158
    private boolean mBuild = true;
1159
 
874 mhunt 1160
    /**in terms of the mChangeType Package field,
902 mhunt 1161
     * when true indicates the major, minor, and patch number will be incremented according to field limits
874 mhunt 1162
     * in terms of the mRippleField Package field,
1163
     * when true indicates the major, minor, patch and build number will be incremented according to field limits
1164
     * @attribute
1165
     */
1166
    private boolean mLimit = false;
1167
 
814 mhunt 1168
    /**constructor
1169
     */
1170
    private VersionNumberingStandard()
1171
    {
1172
      mLogger.debug("VersionNumberingStandard");
1173
    }
1174
 
874 mhunt 1175
    /**sets mBuild true, mMajor false, mMinor false, mPatch false, mLimit false
814 mhunt 1176
     */
1177
    void setBuild()
1178
    {
1179
      mLogger.debug("setBuild");
1180
      mBuild = true;
1181
      mMajor = false;
1182
      mMinor = false;
1183
      mPatch = false;
874 mhunt 1184
      mLimit = false;
814 mhunt 1185
    }
1186
 
874 mhunt 1187
    /**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit false
814 mhunt 1188
     */
1189
    void setMajor()
1190
    {
1191
      mLogger.debug("setMajor");
1192
      mBuild = false;
1193
      mMajor = true;
1194
      mMinor = false;
1195
      mPatch = false;
874 mhunt 1196
      mLimit = false;
814 mhunt 1197
    }
1198
 
902 mhunt 1199
    /**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit limit
1200
     */
1201
    void setMajor( boolean limit )
1202
    {
1203
      mLogger.debug("setMajor " + limit);
1204
      mBuild = false;
1205
      mMajor = true;
1206
      mMinor = false;
1207
      mPatch = false;
1208
      mLimit = limit;
1209
    }
1210
 
874 mhunt 1211
    /**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit false
814 mhunt 1212
     */
1213
    void setMinor()
1214
    {
1215
      mLogger.debug("setMinor");
1216
      mBuild = false;
1217
      mMajor = false;
1218
      mMinor = true;
1219
      mPatch = false;
874 mhunt 1220
      mLimit = false;
814 mhunt 1221
    }
1222
 
902 mhunt 1223
    /**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit limit
1224
     */
1225
    void setMinor( boolean limit )
1226
    {
1227
      mLogger.debug("setMinor " + limit);
1228
      mBuild = false;
1229
      mMajor = false;
1230
      mMinor = true;
1231
      mPatch = false;
1232
      mLimit = limit;
1233
    }
1234
 
874 mhunt 1235
    /**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit false
814 mhunt 1236
     */
1237
    void setPatch()
1238
    {
1239
      mLogger.debug("setPatch");
1240
      mBuild = false;
1241
      mMajor = false;
1242
      mMinor = false;
1243
      mPatch = true;
874 mhunt 1244
      mLimit = false;
814 mhunt 1245
    }
1246
 
902 mhunt 1247
    /**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit limit
1248
     */
1249
    void setPatch( boolean limit )
1250
    {
1251
      mLogger.debug("setPatch");
1252
      mBuild = false;
1253
      mMajor = false;
1254
      mMinor = false;
1255
      mPatch = true;
1256
      mLimit = limit;
1257
    }
1258
 
874 mhunt 1259
    /**sets mBuild false, mMajor false, mMinor false, mPatch false, mLimit true
1260
     */
1261
    void setLimit()
1262
    {
1263
      mLogger.debug("setPatch");
1264
      mBuild = false;
1265
      mMajor = false;
1266
      mMinor = false;
1267
      mPatch = false;
1268
      mLimit = true;
1269
    }
1270
 
814 mhunt 1271
  }
1272
 
1273
}