#!/usr/bin/perl -w
use strict;
use diagnostics

# Copyright (c) Cambia Networks 2001

=pod
=head1 syncshadowdir.pl

  This little script will try to recover
  all changes from the shadow directory 
  to a mysql database.  
  
  The shadow directory is different than the
  shadowdb.  If you have the shadowdb enabled
  go use the syncshadowdb script.

  This script cannot recover what is not in
  the shadow dir.  This includes..
     * comments of components
     * owners of components
     * the "activity log"
    
  This script has not be modified yet to recover...
     * bug dependencies
     * cc (carbon copy) recipients.
  They would not be difficult, but are not used
  much by our database, and I need to go home.

  Warning: Don't leave this as executable in the
  bugzilla directory.  You don't want people
  running it from a browser.

=cut

require "globals.pl";

my @bugIds = glob("shadow/*");


sub matchProblem
{
   print("match problem\n$_[0]\n\n");
   die();
}

ConnectToDatabase();

sub GetLongComment
{
   my $fd = $_[0];

   my $who;
   my $description;
   my $datetime = "0000-00-00 00:00:00";
   while(1) {  # for every line of the description
      my $line = <$fd>;
      last if(!defined($line));
      if($line =~ /^------- Additional Comments From (\S+)\s+(\d\d\d\d-\d\d-\d\d \d\d:\d\d) -------/) {
         $who = $1;
         $datetime = "$2:00";
         last;
      };
      $description .= $line;
   }
   return($description,$who,$datetime);
}

# Incidentally, this will create a product too if needed
sub CreateVersionIfMissing
{
   my ($version,$product) = @_;
   print("Creating Version ($version of $product)\n");
   my $query = # check for components
      "SELECT value FROM versions WHERE\n" .
      "    program = " . SqlQuote($product) . " AND\n" .
      "    value = " . SqlQuote($version) . "\n";
   SendSQL($query);
   my $exists = FetchOneColumn();
   if(!$exists) {  # this added description
      $query = # check for components
         "INSERT into versions (value, program)\n" .
         "    VALUES (" . SqlQuote($version) . ",\n" .
         "            " . SqlQuote($product) . ")\n";
      SendSQL($query);
   };
}

# Incidentally, this will create a product too if needed
sub CreateComponentIfMissing
{
   my ($component,$product) = @_;
   print("Creating Component ($component of $product)\n");
   my $query = # check for components
      "SELECT value FROM components WHERE\n" .
      "    program = " . SqlQuote($product) . " AND\n" .
      "    value = " . SqlQuote($component) . "\n";
   SendSQL($query);
   my $exists = FetchOneColumn();
   if(!$exists) {  # this added description
      $query = # check for components
         "INSERT into components (value, program, description)\n" .
         "    VALUES (" . SqlQuote($component) . ",\n" .
         "            " . SqlQuote($product) . ",\n" .
         "            " . SqlQuote($component) . ")\n";
      SendSQL($query);
   };
}

# Incidentally, this will create a product too if needed
sub CreateMilestoneIfMissing
{
   my ($milestone,$product) = @_;
   print("Creating Version ($milestone of $product)\n");
   my $query = # check for components
      "SELECT value FROM milestones WHERE\n" .
      "    product = " . SqlQuote($product) . " AND\n" .
      "    value = " . SqlQuote($milestone) . "\n";
   SendSQL($query);
   my $exists = FetchOneColumn();
   if(!$exists) {  # this added description
      $query = # check for components
         "INSERT into milestones (value, product)\n" .
         "    VALUES (" . SqlQuote($milestone) . ",\n" .
         "            " . SqlQuote($product) . ")\n";
      SendSQL($query);
   };
}

=pod
# This is an example shadow file
# Sometimes some of the lines don't exist.

+============================================================================+
| test                                                                       |
+----------------------------------------------------------------------------+
|        Bug #: 1201                        Product: Infomation Services     |
|       Status: RESOLVED                    Version: unspecified             |
|   Resolution: INVALID                    Platform: Other                   |
|     Severity: normal                   OS/Version: other                   |
|     Priority: P2                        Component: Other                   |
+----------------------------------------------------------------------------+
|  Assigned To: rdean@cambianetworks.com                                     |
|  Reported By: pcarnathan@cambianetworks.com                                |
|      CC list: Cc:                                                          |
+----------------------------------------------------------------------------+
|    Milestone: TargetMilestone: ---                                         |
|          URL:                                                              |
+============================================================================+
|                              DESCRIPTION                                   |
This is a test

------- Additional Comments From rdean@cambianetworks.com  2001-07-19 17:31 -------
This was a test

------- Additional Comments From rdean@cambianetworks.com  2001-07-19 17:35 -------
Another test
=cut

while(my $bugfile = pop(@bugIds)) {
   $bugfile =~ m|/([^/]*)$|;  # grab the filename (after last slash)
   my $id = $1;
   print("processing bug #$id\n");
   if($id !~ /^(\d+)$/) {  # is it not just numeric
      print("bug number not numeric?\n");
      next;
   };
   if(!open(BF,"<$bugfile")) { # open bugfile used for emails
      print("could not open \"$bugfile\" file!\n");
      next;
   }
   my $junk = <BF>; # skip line 1 of equals
   $junk =~ /^\+\={76}\+$/ or print("bad line 1\n");;

   my $short_desc = <BF>;  # line 2
   $short_desc =~ s/^\|\ // or matchProblem($junk);  # remove leading characters
   $short_desc =~ s/\s+\|\s+// or matchProblem($junk);  # remove trailing characters
   print("  short_desc: <<$short_desc>>\n");

   $junk = <BF>; # skip line 3 of dashes
   $junk =~ /^\+\-{76}\+$/ or matchProblem($junk);

   $junk = <BF>; # line 4
   $junk =~ m/Bug #: (\d+)/ or matchProblem($junk);
   if($1 != $id) {
      printf("  bug # in shadow file ($1) didn't agree with filename ($id)!\n");
      next;
   };
   $junk =~ m/Product: (.+?)\s+\|\s*$/ or matchProblem($junk);
   my $product = $1;
   print("  product: <<$product>>\n");

   $junk = <BF>;  # line 5
   $junk =~ m/Status: (\S+)/ or matchProblem($junk);
   my $bug_status = $1;
   print("  bug_status: <<$bug_status>>\n");
   $junk =~ m/Version: (.+?)\s+\|\s*$/ or matchProblem($junk);
   my $version = $1;
   print("  product: <<$version>>\n");

   $junk = <BF>;  # line 6
   $junk =~ m/Resolution:\s+(.*?)\s+Platform/ or matchProblem($junk);
   my $resolution = $1;
   print("  resolution: <<$resolution>>\n");
   $junk =~ m/Platform: (.+?)\s+\|\s*$/ or matchProblem($junk);
   my $rep_platform = $1;
   print("  rep_platform: <<$rep_platform>>\n");

   $junk = <BF>;  # line 7
   $junk =~ m/Severity: (\S+)/ or matchProblem($junk);
   my $bug_severity = $1;
   print("  bug_severity: <<$bug_severity>>\n");
   $junk =~ m/OS.Version: (.+?)\s+\|\s*$/ or matchProblem($junk);
   my $op_sys = $1;
   print("  op_sys: <<$op_sys>>\n");

   $junk = <BF>;  # line 8
   $junk =~ m/Priority: (\S+)/ or matchProblem($junk);
   my $priority = $1;
   print("  priority: <<$priority>>\n");
   $junk =~ m/Component: (.+?)\s+\|\s*$/ or matchProblem($junk);
   my $component = $1;
   print("  component: <<$component>>\n");

   $junk = <BF>; # skip line 9 of dashes
   $junk =~ /^\+\-{76}\+$/ or matchProblem($junk);

   $junk = <BF>;  # line 10
   $junk =~ m/Assigned To: (\S+)\s*\|\s*$/ or matchProblem($junk);
   my $assigned_to = $1;
   print("  assigned_to: <<$assigned_to>>\n");

   $junk = <BF>;  # line 11
   $junk =~ m/Reported By: (\S+)\s*\|\s*$/ or matchProblem($junk);
   my $reporter = $1;
   print("  reporter: <<$reporter>>\n");

   $junk = <BF>;  # line 12
   my $cc = "Cc: ";
   if($junk =~ m/CC list: (.+?)\s*\|\s*$/) {
      $cc = $1;
      print("  cc: <<$cc>>\n");

      $junk = <BF>; # skip line 13 of dashes
   };
   $junk =~ /^\+\-{76}\+$/ or matchProblem($junk);

   $junk = <BF>;  # line 14
   my $target_milestone = "---";
   if($junk =~ m/Milestone: TargetMilestone: (.+?)\s*\|\s*$/) {
      $target_milestone = $1;
      print("  target_milestone: <<$target_milestone>>\n");

      $junk = <BF>;  # line 15
   };
   $junk =~ m/URL: (.*?)\s*\|\s*$/ or matchProblem($junk);
   my $url = $1;
   print("  url: <<$url>>\n");

   $junk = <BF>;  # line 16?
   if($junk =~ m/Depend/) {

      $junk = <BF>; # skip line of equals
   };
   $junk =~ /^\+\={76}\+$/ or matchProblem($junk);

   $junk = <BF>; # 
   $junk =~ /DESCRIPTION/ or matchProblem($junk);
   my ($description,$nextwho,$nextdatetime) = GetLongComment(*BF);
   my ($who, $datetime) = ($reporter,$nextdatetime);  # approximate datetime
   CreateComponentIfMissing($component,$product);
   CreateVersionIfMissing($version,$product);
   CreateMilestoneIfMissing($target_milestone,$product);
   my $query = 
      " SELECT bugs.bug_id\n".
      "FROM bugs\n".
      "WHERE bugs.bug_id = $id\n";
   SendSQL($query);
   if (FetchSQLData()) {  # if bug exists
      print(" already exists\n");
      $query = "UPDATE bugs SET\n".
         "   product=" . SqlQuote($product) . ",\n" .
         "   version=" . SqlQuote($version) . ",\n" .
         "   bug_status=" . SqlQuote($bug_status) . ",\n" . 
         "   resolution=" . SqlQuote($resolution) . ",\n" .
         "   priority=" . SqlQuote($priority) . ",\n" .
         "   component=" . SqlQuote($component) . ",\n" .
         "   bug_severity=" . SqlQuote($bug_severity) . ",\n" .
         "   short_desc=" . SqlQuote($short_desc) . ",\n" .
         "   target_milestone=" . SqlQuote($target_milestone) . ",\n" .
         "   op_sys=" . SqlQuote($op_sys) . ",\n" .
         "   rep_platform=" . SqlQuote($rep_platform) . ",\n" .
         "   assigned_to=" . DBNameToIdAndCheck($assigned_to,"force") . ",\n" .
         "   reporter=" . DBNameToIdAndCheck($reporter,"force") . "\n" .
         "   WHERE bug_id=$id\n";
      #print("$query\n\n");
      SendSQL($query);
      while(1) {  # for every description (we possibly add)
         ($who, $datetime) = ($nextwho,$nextdatetime);
         last if(eof(BF));
         ($description,$nextwho,$nextdatetime) = GetLongComment(*BF);
         $query = "SELECT bug_id FROM longdescs \n".
                  "WHERE (bug_id = $id\n".
                  "AND thetext = ".SqlQuote($description).")\n";
         SendSQL($query);
         my $exists = FetchOneColumn();
         if(!$exists) {  # this added description
            $query = "INSERT INTO longdescs (bug_id, who, bug_when, thetext) VALUES \n" .
              "  ($id, ".SqlQuote(DBNameToIdAndCheck($who,"force")).", \n".
              " '$datetime',\n  " . SqlQuote($description) . ")";
            SendSQL($query);
         }
      };

   } else {  # else the bug doesn't exist
      print(" did not exists\n");
      my $query = "INSERT INTO bugs (\n" .
                  " bug_id,product,version,bug_status,resolution,priority, \n".
                  " component, bug_severity, assigned_to, reporter, short_desc,\n".
                  " target_milestone, op_sys, rep_platform, creation_ts, groupset)  \n".
                  " VALUES (\n".
                  SqlQuote($id) . ",\n" .                                  
                  SqlQuote($product) . ",\n" .                                  
                  SqlQuote($version) . ",\n" .                                  
                  SqlQuote($bug_status) . ",\n" .                                  
                  SqlQuote($resolution) . ",\n" .                                  
                  SqlQuote($priority) . ",\n" .                                  
                  SqlQuote($component) . ",\n" .                                  
                  SqlQuote($bug_severity) . ",\n" .                                  
                  SqlQuote(DBNameToIdAndCheck($assigned_to,"force")) . ",\n" .                                  
                  SqlQuote(DBNameToIdAndCheck($reporter,"force")) . ",\n" .                                  
                  SqlQuote($short_desc) . ",\n" .  
                  SqlQuote($target_milestone) . ",\n" .    
                  SqlQuote($op_sys) . ",\n" .    
                  SqlQuote($rep_platform) . ",\n" .    
                  # we should use the $datetime instead of now(), 
                  # but need to check for zero
                  "now() , 0)\n";
      SendSQL($query);
      while(1) {  # for every description to add
         $query = "INSERT INTO longdescs (bug_id, who, bug_when, thetext) VALUES \n" .
           "  ($id, ".SqlQuote(DBNameToIdAndCheck($who,"force")).", \n".
           " '$datetime',\n  " . SqlQuote($description) . ")";
         SendSQL($query);
         last if(eof(BF));
         ($who, $datetime) = ($nextwho,$nextdatetime);
         ($description,$nextwho,$nextdatetime) = GetLongComment(*BF);
      };
   };
} 

print("####### finished\n");
exit(0);

