Some JIRA scripts
[clearscm.git] / audience / JIRA / lib / BugzillaUtils.pm
diff --git a/audience/JIRA/lib/BugzillaUtils.pm b/audience/JIRA/lib/BugzillaUtils.pm
new file mode 100644 (file)
index 0000000..899f506
--- /dev/null
@@ -0,0 +1,322 @@
+=pod
+
+=head1 NAME $RCSfile: BugzillaUtils.pm,v $
+
+Some shared functions dealing with Bugzilla. Note this uses DBI to directly
+access Bugzilla's database. This requires that your userid was granted access.
+For this I setup adefaria with pretty much read only access.
+
+=head1 VERSION
+
+=over
+
+=item Author
+
+Andrew DeFaria <Andrew@ClearSCM.com>
+
+=item Revision
+
+$Revision: 1.0 $
+
+=item Created
+
+Fri Mar 12 10:17:44 PST 2004
+
+=item Modified
+
+$Date: 2013/05/30 15:48:06 $
+
+=head1 ROUTINES
+
+The following routines are exported:
+
+=cut
+
+package BugzillaUtils;
+
+use strict;
+use warnings;
+
+use base 'Exporter';
+
+use FindBin;
+use Display;
+use Carp;
+use DBI;
+
+use lib 'lib';
+
+use JIRAUtils;
+
+our $bugzilla;
+
+our @EXPORT = qw (
+  openBugzilla
+  getRelationships
+  getDependencies
+  getBlockers
+  getDuplicates
+  getRelated
+  getBug
+  getBugComments
+  getWatchers
+);
+
+sub _checkDBError ($$) {
+  my ($msg, $statement) = @_;
+
+  my $dberr    = $bugzilla->err;
+  my $dberrmsg = $bugzilla->errstr;
+
+  $dberr    ||= 0;
+  $dberrmsg ||= 'Success';
+
+  my $message = '';
+
+  if ($dberr) {
+    my $function = (caller (1)) [3];
+
+    $message = "$function: $msg\nError #$dberr: $dberrmsg\n"
+             . "SQL Statement: $statement";
+  } # if
+
+  $main::log->err ($message, $dberr) if $dberr;
+
+  return;
+} # _checkDBError
+
+sub openBugzilla (;$$$$) {
+  my ($dbhost, $dbname, $dbuser, $dbpass) = @_;
+
+  $dbhost //= 'jira-dev';
+  $dbname //= 'bugzilla';
+  $dbuser //= 'adefaria';
+  $dbpass //= 'reader';
+  
+  $main::log->msg ("Connecting to Bugzilla ($dbuser\@$dbhost)");
+  
+  $bugzilla = DBI->connect (
+    "DBI:mysql:$dbname:$dbhost",
+    $dbuser,
+    $dbpass, {
+      PrintError => 0,
+      RaiseError => 1,
+    },
+  );
+  
+  _checkDBError 'Unable to execute statement', 'Connect';
+
+  return $bugzilla;
+} # openBugzilla
+
+sub getBug ($;@) {
+  my ($bugid, @fields) = @_;
+  
+  push @fields, 'short_desc' unless @fields;
+  
+  my $statement = 'select ' . join (',', @fields) .
+                  " from bugs where bug_id = $bugid";
+                  
+  my $sth = $bugzilla->prepare ($statement);
+
+  _checkDBError 'Unable to prepare statement', $statement;
+  
+  _checkDBError 'Unable to execute statement', $statement;
+
+  $sth->execute;
+
+  return $sth->fetchrow_hashref;
+} # getBug
+
+sub getBugComments ($) {
+  my ($bugid) = @_;
+  
+  my $statement = <<"END";
+select 
+  bug_id, 
+  bug_when, 
+  substring_index(login_name,'\@',1) as username,
+  thetext
+from
+  longdescs,
+  profiles
+where
+  who    = userid and
+  bug_id = $bugid 
+END
+  
+  my $sth = $bugzilla->prepare ($statement);
+  
+  _checkDBError 'Unable to prepare statement', $statement;
+
+  $sth->execute;
+  
+  _checkDBError 'Unable to execute statement', $statement;
+  
+  my @comments;
+  
+  while (my $comment = $sth->fetchrow_hashref) {
+    my $commentText = <<"END";
+The following comment was entered by [~$comment->{username}] on $comment->{bug_when}:
+
+$comment->{thetext}
+END
+
+    push @comments, $commentText;
+  } # while
+  
+  return \@comments;
+} # getBugComments
+
+sub getRelationships ($$$$@) {
+  my ($table, $returnField, $testField, $relationshipType, @bugs) = @_;
+  
+  $main::log->msg ("Getting $relationshipType");
+  
+  my $statement = "select $returnField from $table where $table.$testField = ?";
+
+  my $sth = $bugzilla->prepare ($statement);
+
+  _checkDBError 'Unable to prepare statement', $statement;
+  
+  my %relationships;
+
+  my %bugmap;
+  
+  map {$bugmap{$_} = 1} @bugs unless %bugmap;
+      
+  for my $bugid (@bugs) {
+    $sth->execute ($bugid);
+    
+    _checkDBError 'Unable to exit statement', $statement;
+    
+    my $result = JIRAUtils::findIssue ($bugid, %bugmap);
+    
+    if ($result =~ /^Unable/) {
+      $main::log->warn ($result);
+      
+      $main::total{'Missing JIRA Issues'}++;
+      
+      undef $result;
+    } elsif ($result =~ /^Future/) {
+      $main::total{'Future JIRA Issues'}++;
+      
+      undef $result;
+    } # if
+    
+    my $jiraIssue = $result;
+    my $key       = $jiraIssue || $bugid;
+
+    my @relationships;
+    my $relations = $sth->fetchall_arrayref;
+    my @relations;
+    
+    map {push @relations, $_->[0]} @$relations;
+    
+    for my $relation (@relations) {
+      $jiraIssue = JIRAUtils::findIssue ($relation);
+      
+      if ($jiraIssue =~ /^Unable/ || $jiraIssue =~ /^Future/) {
+        $main::log->warn ($jiraIssue);
+
+        $main::total{'Missing JIRA Issues'}++ if $jiraIssue =~ /^Unable/;
+        $main::total{'Future JIRA Issues'}++  if $jiraIssue =~ /^Future/;
+        
+        push @relationships, $relation;
+      } else {
+        push @relationships, $jiraIssue;
+      } # if
+    } # for
+      
+    push @{$relationships{$key}}, @relationships if @relationships;
+  } # for
+  
+  $main::total{$relationshipType} = keys %relationships;
+  
+  return \%relationships;
+} # getRelationships
+
+sub getDependencies (@) {
+  my (@bugs) = @_;
+
+  return getRelationships (
+    'dependencies', # table 
+    'dependson',    # returned field
+    'blocked',      # test field
+    'Depends on',   # relationship
+    @bugs
+  );
+} # getDependencies
+
+sub getBlockers (@) {
+  my (@bugs) = @_;
+  
+  return getRelationships (
+    'dependencies', 
+    'blocked', 
+    'dependson', 
+    'Blocks',
+    @bugs
+  );
+} # getBlockers
+
+sub getDuplicates (@) {
+  my (@bugs) = @_;
+  
+  return getRelationships (
+    'duplicates', 
+    'dupe', 
+    'dupe_of', 
+    'Duplicates',
+    @bugs
+  );
+} # getDuplicates
+
+sub getRelated (@) {
+  my (@bugs) = @_;
+  
+  return getRelationships (
+    'bug_see_also', 
+    'value', 
+    'bug_id', 
+    'Relates',
+    @bugs
+  );
+} # getRelated
+
+sub getWatchers ($) {
+  my ($bugid) = @_;
+  
+  my $statement = <<"END";
+select 
+  profiles.login_name
+from 
+  cc,
+  profiles
+where 
+  cc.who = profiles.userid and
+  bug_id = ?
+END
+
+  my $sth = $bugzilla->prepare ($statement);
+
+  _checkDBError 'Unable to prepare statement', $statement;
+
+  $sth->execute ($bugid);
+
+  _checkDBError 'Unable to execute statement', $statement;
+
+  my @rows = @{$sth->fetchall_arrayref};
+
+  my %watchers;
+
+  for (@rows) {
+    if ($$_[0] =~ /(.*)\@/) {
+      $watchers{$1} = 1;
+    } # if
+
+    $main::total{'Watchers Processed'}++;  
+  } # for
+
+  return %watchers;
+} # getWatchers
\ No newline at end of file