2 ################################################################################
5 # Description: Merge the old TO (Teton) and Prod databases to the new Cont
6 # (Controller) database. This process assumes the new database
7 # is empty and that there are two "masterdb"'s named From and To.
8 # These are Clearquest connection profiles and From and To refer
9 # to the names given in the Clearquest Maintainance Tool for the
10 # connections. From contains both the TO and Prod databases and
11 # the To connection contains the Cont database.
13 # Note that it is also assumed that the Cont database has had it's
14 # code page set to US ASCII. This script will translate non US
15 # ASCII characters in the from databases to HTML equivalents.
17 # Author: Andrew@DeFaria.com
18 # Created: Fri Sep 23 17:27:58 PDT 2005
21 # (c) Copyright 2005, Andrew@DeFaria.com, all rights reserved
23 ################################################################################
29 our ($me, $SEPARATOR);
31 my ($abs_path, $lib_path);
34 # Extract relative path and basename from script name.
35 $0 =~ /(.*)[\/\\](.*)/;
37 $abs_path = (!defined $1) ? "." : File::Spec->rel2abs ($1);
38 $me = (!defined $2) ? $0 : $2;
41 # Remove .pl for Perl scripts that have that extension
44 # Define the path SEPARATOR
45 $SEPARATOR = ($^O =~ /MSWin/) ? "\\" : "/";
48 $lib_path = "$abs_path" . $SEPARATOR . ".." . $SEPARATOR . "lib";
50 # Add the appropriate path to our modules to @INC array.
51 unshift (@INC, "$abs_path");
52 unshift (@INC, "$lib_path");
60 my $from_db_connection_name = "2003.06.00";
61 my $to_db_connection_name = "2005.02.00";
67 display "ERROR: $msg\n" if defined $msg;
69 display "Usage: $me\t[-u] [-v] [-d] [-id <id>]
70 [-from <connection name>]
71 [-to <connection name>]
76 -v: Turn on verbose mode
77 -d: Turn on debug mode
78 -id <id>: Process only the specified defect <id>
79 (Default: Process all defects)
80 -from <connection name>: Specify the from connection name
81 (Default: $from_db_connection_name)
82 -to <connection name>: Specify the to connection name
83 (Default: $to_db_connection_name)";
90 my $record_name = shift;
91 my $current_id = shift;
96 while ($current_id < $dest_id) {
97 # Create a new entity and get it's ID until we reach $dest_id
98 $entity = $to->BuildEntity ($record_name);
99 $current_id = $entity->GetFieldValue ("id")->GetValue;
101 # Change $current_id to just the number portion
102 $current_id = substr $current_id, 4, 8;
104 # Burn the id if it is not equal to the $dest_id
105 $entity->Revert if $current_id < $dest_id;
113 my $record_name = shift;
118 # There is no corresponding Submit state in Cont so we cannot
119 # transition it's state. For now we will leave it Assigned.
120 return if $state eq "Submit";
122 # State transition matrix: This hash defines a state to get to and
123 # an array of how to get there.
124 my %state_transition_matrix = (
140 "Awaiting_Cust_Verify" => [
143 "VerifiedPendingCustVerify"
150 "Verified_Cust_Accepted" => [
153 "VerifiedPendingCustVerify",
158 # Not transition through the necessary states
159 my $current_state = $state;
160 my @actions = @{$state_transition_matrix {$current_state}};
162 debug "Transitioning $id to $current_state State";
165 debug "Applying action $_";
167 my $new_entity = $db->GetEntity ($record_name, $id);
169 $db->EditEntity ($new_entity, $_);
171 my $errmsg = $new_entity->Validate;
175 $log->err ("\n$id\n$errmsg");
178 # Post record to database
184 sub TransferDefects {
189 my $record_name = shift;
190 my $search_id = shift;
196 if (defined $search_id) {
197 $result = GetDefectRecord $log, $from, $record_name, $search_id;
199 $result = GetAllDefectRecords $log, $from, $record_name;
204 my $old_bufffer_status = $|;
205 $| = 1; # Turn off buffering
209 # Seed $current_id - IOW what is the current ID in the destination
212 if (!defined $search_id) {
213 my $entity = $to->BuildEntity ($record_name);
214 $current_id = $entity->GetFieldValue ("id")->GetValue;
217 # Now for each record returned by the query...
218 while ($result->MoveNext == $CQPerlExt::CQ_SUCCESS) {
219 # GetEntity by using $id
220 my $id = $result->GetColumnValue (1);
221 my $from_entity = $from->GetEntity ($record_name, $id);
224 my $history_filename = "history.txt";
227 if (!defined $search_id) {
228 # Check to see if $id > $current_id. If so then we can't
229 # proceed. If not then we need to burn up some IDs.
230 my $current_id_nbr = substr $current_id, 4, 8;
233 if ($id =~ /^Prod/) {
234 $dest_id_nbr = substr $id, 4, 8;
236 $dest_id_nbr = 20000 + (substr $id, 2, 8);
239 if ($current_id_nbr > $dest_id_nbr) {
240 error "Unable to sequence merge", 1;
241 } elsif ($current_id_nbr < $dest_id_nbr) {
242 $to_entity = BurnIDsTil $log, $to, $record_name, $current_id_nbr, $dest_id_nbr;
245 # Since $search_id is defined we're doing a single ID, in test
246 # mode, so generate a new $to_entity. IOW there is no sequencing
248 $to_entity = $to->BuildEntity ($record_name);
251 $log->msg (++$nbr . ": Merging ID $id ", "nolf");
254 foreach (@field_list) {
256 my $value = $from_entity->GetFieldValue ($name)->GetValue;
258 # Here we handle the differences between records..
259 if ($dbname eq "TO") {
260 ## Field Translations
262 # TO: defect: AdvancedFeature -> Cont: defect: Advanced_Feature
263 if ($name eq "AdvancedFeature") {
264 $name = "Advanced_Feature";
265 AddToFieldChoiceList $to, $to_entity, $name, $name, $value;
268 # TO: defect: Fixed_In_Project -> Cont: defect: Fixed_In_Project
269 # but as a reference to Cont: Project
270 AddToFieldChoiceList $to, $to_entity, "Project", $name, $value if $name eq "Fixed_In_Project";
272 # TO: defect: Found_In_Project -> Cont: defect: Found_In_Project
273 # but as a reference to Cont: Project
274 AddToProject $log, $to, $value if $name eq "Found_In_Project";
276 # TO: defect: Fixed_In_SW_Version -> Cont: defect: Fixed_In_SW_Version
277 if ($name eq "Fixed_In_SW_Version") {
278 $value = "N/A" if $value eq "";
281 # TO: defect: History -> Cont: defect: <AttachmentBRCM>
282 # Transfer history item to an attachment
283 if ($name eq "History") {
284 TransferHistory ($from_entity, $to_entity, $history_filename);
289 # TO: defect: GatingItem -> Cont: defect: Gating_Item_HW
290 $name = "Gating_Item_SW" if $name eq "GatingItem";
292 # TO: defect: HUT_Version -> Cont: defect: Board_Revision
293 if ($name eq "HUT_Version") {
294 $name = "Board_Revision";
295 $value = "Not Applicable" if $value eq "N/A";
296 AddToFieldChoiceList $to, $to_entity, $name, $name, $value;
299 # TO: defect: ReportedBy -> Cont: defect: Reported_By
300 if ($name eq "ReportedBy") {
301 $name = "Reported_By";
302 AddToFieldChoiceList $to, $to_entity, $name, $name, $value
305 # TO: defect: NoteBugReview -> Cont: defect: Bug_Review_Note
306 $name = "Bug_Review_Note" if $name eq "NoteBugReview";
308 # TO: defect: NoteBRCMOnly -> Cont: defect: Broadcom_Only_Note
309 $name = "Broadcom_Only_Note" if $name eq "NoteBRCMOnly";
311 # TO: defect: Open_Close_Status -> Cont: defect: Active_Deferred_Status
312 $name = "Active_Deferred_Status" if $name eq "Open_Close_Status";
314 # TO: defect: SQATestCase -> Cont: defect: PQATestCase
315 if ($name eq "SQATestCase") {
316 $name = "PQATestCase";
317 $value = "N/A" if $value eq "";
320 # TO: defect: Title_2 -> Cont: defect: Title
321 if ($name eq "Title_2") {
322 # There are some blank titles!
323 $value = "N/A" if $value eq "";
329 next if $name eq "AttachmentsBRCM" or
330 $name eq "Project" or
331 $name eq "PendingHWSWReleases" or
332 $name eq "TestBlocking";
333 } elsif ($dbname eq "Prod") {
334 ## Field Translations
336 # Prod: defect: AdvancedFeature -> Cont: defect: Advanced_Feature
337 if ($name eq "AdvancedFeature") {
338 $name = "Advanced_Feature";
339 AddToFieldChoiceList $to, $to_entity, $name, $name, $value;
342 # Prod: defect: Fixed_In_Project -> Cont: defect: Project
343 # but as a reference to Cont: Project
344 AddToFieldChoiceList $to, $to_entity, "Project", $name, $value if $name eq "Fixed_In_Project";
346 # Prod: defect: Fixed_In_SW_Version -> Cont: defect: Fixed_In_SW_Version
347 if ($name eq "Fixed_In_SW_Version") {
348 $value = "N/A" if $value eq "";
351 # Prod: defect: History -> Cont: defect: <AttachmentBRCM>
352 # Transfer history item to an attachment
353 if ($name eq "History") {
354 TransferHistory ($from_entity, $to_entity, $history_filename);
357 # Prod: defect: Category -> Cont: defect: Category
358 if ($name eq "Category") {
359 # There is no "Hardware" anymore so translating them to "Hardware - Board"
360 if ($value eq "Hardware") {
361 $value = "Hardware - Board";
365 # Prod: defect: GatingItem -> Cont: defect: Gating_Item_HW
366 $name = "Gating_Item_SW" if $name eq "GatingItem";
368 # Prod: defect: HUT_Version -> Cont: defect: Board_Revision
369 if ($name eq "HUT_Version") {
370 $name = "Board_Revision";
371 $value = $value ne "" ? $value : "Not Applicable";
372 $value = "Not Applicable" if $value eq "N/A";
373 if ($value eq "BCM95704CA40 v1.0 revA0 ") {
374 # Trailing blank is wrong! - Removing it
375 $value = "BCM95704CA40 v1.0 revA0";
377 AddToFieldChoiceList $to, $to_entity, $name, $name, $value;
380 # Prod: defect: Issue_Classification -> Cont: defect: Issue_Classification
381 # There are no: Hardware in the new Cont database so we'll map it to
383 if ($name eq "Issue_Classification") {
384 $value = "Requirement" if $value eq "Hardware";
387 # Prod: defect: NoteBugReview -> Cont: defect: Bug_Review_Note
388 $name = "Bug_Review_Note" if $name eq "NoteBugReview";
390 # Prod: defect: NoteBRCMOnly -> Cont: defect: Broadcom_Only_Note
391 $name = "Broadcom_Only_Note" if $name eq "NoteBRCMOnly";
393 # Prod: defect: Open_Close_Status -> Cont: defect: Active_Deferred_Status
394 $name = "Active_Deferred_Status" if $name eq "Open_Close_Status";
396 # Prod: defect: Project -> Cont: defect: Found_In_Project
397 if ($name eq "Project") {
398 AddToProject $log, $to, $value;
399 $name = "Found_In_Project";
402 # Prod: defect: ReportedBy -> Cont: defect: Reported_By
403 if ($name eq "ReportedBy") {
404 $name = "Reported_By";
405 AddToFieldChoiceList $to, $to_entity, $name, $name, $value
408 # Prod: defect: Resolution -> Cont: defect: Resolution
409 if ($name eq "Resolution") {
410 # There is no "HW Fix" anymore so translating them to "Hw Fix - Board"
411 if ($value eq "HW Fix") {
412 $value = "HW Fix - Board";
413 } elsif ($value eq "MAC Core") {
414 $value = "HW Fix - MAC Core";
418 # Prod: defect: Software_Version -> Cont: defect: Software_Version
419 if ($name eq "Software_Version") {
420 $value = "N/A" if $value eq "" or $value eq " ";
423 # Prod: defect: Title -> Cont: defect: Title
424 if ($name eq "Title") {
425 $value = $value ne "" ? $value : "<N/A>";
429 # Prod: defect: SQATestcase -> Cont: defect: PQATestCase
430 if ($name eq "SQATestCase") {
431 $name = "PQATestCase";
432 $value = "N/A" if $value eq "";
435 # Prod: defect: Title_2 -> Cont: defect: Title
436 $name = "Title" if $name eq "Title_2";
439 next if $name eq "AttachmentBRCM" or
440 $name eq "Project_Name" or
441 $name eq "PendingHWSWReleases" or
442 $name eq "TestBlocking";
445 # Check field for non US ASCII characters and fix them
446 $value = CheckField $dbname, $record_name, $id, $name, $value;
448 ## Handle dynamic choice lists
450 # While the field name is DeferredToProject, it's corresponding
451 # Dynamic list name is actually Project
452 AddToFieldChoiceList $to, $to_entity, "Project", $name, $value if $name eq "DeferredToProject";
454 # While the field name is CommittedToProject, it's corresponding
455 # Dynamic list name is actually Project
456 AddToFieldChoiceList $to, $to_entity, "Project", $name, $value if $name eq "CommittedToProject";
458 if ($name eq "HUT") {
459 $value = "BRCM Copper (do not use)" if $value eq "Broadcom Copper";
460 $value = "BRCM Fiber (do not use)" if $value eq "Broadcom Fiber Optic";
463 AddToFieldChoiceList $to, $to_entity, $name, $name, $value if $name eq "HUT";
465 if ($name eq "HUT_Revision") {
469 $value eq "\?\?\?" or
470 $value eq "A0-A4,B0-B1" or
472 $value eq "all revisions" or
478 $value = "A0" if $value eq "BCM5752 A0";
479 $value = "A1" if $value eq "BCM5752 A1 10x10 package";
480 $value = "A2" if $value eq "A2 (A3 Silent)";
481 $value = "A3" if $value eq "A3 silent (A2)";
482 $value = "B1" if $value eq "B1/A1";
483 AddToFieldChoiceList $to, $to_entity, $name, $name, $value;
486 if ($name eq "Service_Pack") {
487 $value = "Not Applicable"
493 $value eq "Notice that QA applies to bootcode + Win + Linux d";
494 $value = "SP3" if $value eq "SP3 ";
495 $value = "SP4" if $value eq "SP4 ";
496 $value = "Suse 9" if $value eq "Suse 9 ";
499 # While the field name is Service_Pack, it's corresponding
500 # Dynamic list name is actually OS_Service_Pack!
501 AddToFieldChoiceList $to, $to_entity, "OS_Service_Pack", $name, $value if $name eq "Service_Pack";
503 AddToFieldChoiceList $to, $to_entity, $name, $name, $value if $name eq "Software";
504 AddToFieldChoiceList $to, $to_entity, $name, $name, $value if $name eq "Visibility";
506 $value = "Novell 6 Pack Beta 3" if $value eq "Novell 6 Pack Beta 3 ";
507 AddToFieldChoiceList $to, $to_entity, $name, $name, $value if $name eq "OS";
510 # Set the field's value
511 $to_entity->SetFieldValue ($name, $value);
516 # Found_On_Gold: Default to "No"
517 $to_entity->SetFieldValue ("Found_On_Gold", "No");
519 # Gating_Item_HW: Default to "No"
520 $to_entity->SetFieldValue ("Gating_Item_HW", "No");
522 # Newly_Introduce: Default to "No"
523 $to_entity->SetFieldValue ("Newly_Introduce", "No");
525 # Root_Caused: Default to "No"
526 $to_entity->SetFieldValue ("Root_Caused", "No");
528 # Throw old ID from Prod or TO into old_id. This can then serve
529 # As a cross reference
530 $to_entity->SetFieldValue ("old_id", $id);
532 # Need to handle attachments differently...
533 @files_created = TransferAttachments $log, $from_entity, $to_entity;
535 # Call the Validate method
536 my $errmsg = $to_entity->Validate;
540 $log->err ("\n$id\n$errmsg");
542 # Post record to database
544 $new_id = $to_entity->GetFieldValue ("id")->GetValue;
545 $log->msg ("-> $new_id");
548 # Clean up files created by TransferAttachments - if any
549 foreach (@files_created) {
553 # Clean up files created by TransferHistory
554 unlink $history_filename;
556 # Transfer State: The entity we just created is now in the
557 # Assigned state. But that's not the same as the state of the
558 # original entity. The following code attempts to fix this.
559 my $old_state = $from_entity->GetFieldValue ("State")->GetValue;
561 TransferState $log, $record_name, $to, $new_id, $old_state;
564 $| = $old_bufffer_status; # Restore buffering
570 if ($ARGV [0] eq "-v") {
571 Display::set_verbose;
573 } elsif ($ARGV [0] eq "-d") {
575 } elsif ($ARGV [0] eq "-id") {
578 Usage "Must specify ID after -id";
582 } elsif ($ARGV [0] eq "-from") {
585 Usage "Must specify <connection name> after -from";
587 $from_db_connection_name = $ARGV [0];
589 } elsif ($ARGV [0] eq "-to") {
592 Usage "Must specify <connection name> after -to";
594 $to_db_connection_name = $ARGV [0];
596 } elsif ($ARGV [0] eq "-u") {
599 Usage "Unknown argument found: " . $ARGV [0];
605 my $log = Logger->new (path => ".");
607 my $process_start_time = time;
610 $log->msg ("Starting Cont session");
611 my $controller = StartSession "Cont", $to_db_connection_name;
616 my $record_name = "defect";
619 $log->msg ("Starting Prod session");
620 my $prod = StartSession ("Prod", $from_db_connection_name);
622 $log->msg ("Transferring Prod:defect -> Cont:defect");
624 $current_id = TransferDefects $log, $prod, $controller, "Prod", $record_name, $id, @old_Prod_defect_fields;
625 $log->msg ("Completed transfer of Prod:defect records");
626 display_duration $start_time, $log;
628 $log->msg ("Ending Prod session");
633 $log->msg ("Starting TO session");
634 my $teton = StartSession "TO", $from_db_connection_name;
636 $log->msg ("Transferring TO:defect -> Cont:defect");
640 my $current_id_nbr = substr $current_id, 4, 8;
641 # Start numbering TO at 20000
642 BurnIDsTil $log, $controller, $record_name, $current_id_nbr, "20000";
644 TransferDefects $log, $teton, $controller, "TO", $record_name, $id, @old_TO_defect_fields;
645 $log->msg ("Completed transfer of TO:defect records");
646 display_duration $start_time, $log;
648 $log->msg ("Ending TO session");
652 $log->msg ("Ending Cont session");
653 EndSession $controller;
655 verbose "Total processing time:";
656 display_duration $process_start_time, $log;