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