217 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
#!/usr/bin/perl
 | 
						|
 | 
						|
use strict;
 | 
						|
 | 
						|
use Config::Simple;
 | 
						|
use DBI;
 | 
						|
use File::Basename;
 | 
						|
use POSIX qw(strftime);
 | 
						|
 | 
						|
use SVN::Core;
 | 
						|
use SVN::Repos;
 | 
						|
use SVN::Fs;
 | 
						|
 | 
						|
my $CFG_FILE = '@CFGDIR@/codepot.ini';
 | 
						|
my $REPOFS = $ARGV[0];
 | 
						|
my $REPOBASE = basename($REPOFS);
 | 
						|
my $REV = $ARGV[1];
 | 
						|
my $USER = $ARGV[2];
 | 
						|
my $PROPNAME = $ARGV[3];
 | 
						|
my $ACTION = $ARGV[4];
 | 
						|
 | 
						|
my $QC = '';
 | 
						|
 | 
						|
# [STDIN] PROPVAL  ** the old property value is passed via STDIN.
 | 
						|
 | 
						|
sub get_config
 | 
						|
{
 | 
						|
	my $cfg = new Config::Simple();
 | 
						|
	
 | 
						|
	if (!$cfg->read ($CFG_FILE))
 | 
						|
	{
 | 
						|
		return undef;
 | 
						|
	}
 | 
						|
	
 | 
						|
	my $config = {
 | 
						|
		database_hostname => $cfg->param ("database_hostname"),
 | 
						|
		database_port => $cfg->param ("database_port"),
 | 
						|
		database_username => $cfg->param ("database_username"),
 | 
						|
		database_password => $cfg->param ("database_password"),
 | 
						|
		database_name => $cfg->param ("database_name"),
 | 
						|
		database_driver => $cfg->param ("database_driver"),
 | 
						|
		database_prefix => $cfg->param ("database_prefix")
 | 
						|
	};
 | 
						|
 | 
						|
	return $config;
 | 
						|
}
 | 
						|
 | 
						|
sub open_database
 | 
						|
{
 | 
						|
	my ($cfg) = @_;
 | 
						|
 | 
						|
	my $dbtype = $cfg->{database_driver};
 | 
						|
	my $dbname = $cfg->{database_name};
 | 
						|
	my $dbhost = $cfg->{database_hostname};
 | 
						|
	my $dbport = $cfg->{database_port};
 | 
						|
 | 
						|
	if ($dbtype eq 'postgre') { $dbtype = 'Pg'; }
 | 
						|
	elsif ($dbtype eq 'oci8') { $dbtype = 'Oracle'; }
 | 
						|
	elsif ($dbtype eq 'mysqli') { $dbtype = 'mysql'; }
 | 
						|
 | 
						|
	my $dbstr;
 | 
						|
	my $dbuser;
 | 
						|
	my $dbpass;
 | 
						|
	if ($dbtype eq 'Oracle')
 | 
						|
	{
 | 
						|
		$QC = '"';
 | 
						|
		$dbstr = "DBI:$dbtype:";
 | 
						|
		$dbuser = $cfg->{database_username} . '/' . $cfg->{database_password} . '@' . $dbhost;
 | 
						|
		$dbpass = '';
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		$dbstr = "DBI:$dbtype:database=$dbname;";
 | 
						|
		if (length($dbhost) > 0) { $dbstr .= "host=$dbhost;"; }
 | 
						|
		if (length($dbport) > 0) { $dbstr .= "port=$dbport;"; }
 | 
						|
 | 
						|
		$dbuser = $cfg->{database_username};
 | 
						|
		$dbpass = $cfg->{database_password};
 | 
						|
	}
 | 
						|
 | 
						|
	my $dbh = DBI->connect(
 | 
						|
		$dbstr, $dbuser, $dbpass,
 | 
						|
		{ RaiseError => 0, PrintError => 0, AutoCommit => 0 }
 | 
						|
	);
 | 
						|
 | 
						|
	return $dbh;
 | 
						|
}
 | 
						|
 | 
						|
sub close_database
 | 
						|
{
 | 
						|
	my ($dbh) = @_;
 | 
						|
	$dbh->disconnect ();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub find_issue_reference_in_commit_message
 | 
						|
{
 | 
						|
	my ($dbh, $prefix, $projectid, $revision, $commit_message) = @_;
 | 
						|
 | 
						|
	# find [[#IXXXX]]
 | 
						|
	my @issue_ids = ($commit_message =~ /\[\[#I(\d+)\]\]/g);
 | 
						|
	# find #XXXX
 | 
						|
	my @issue_ids2 = ($commit_message =~ /(^|[^#])#(\d+)(\D|$)/g);
 | 
						|
 | 
						|
	# find unique issue ids in the findings.
 | 
						|
	my %tmp;
 | 
						|
	@tmp{@issue_ids} = 1;
 | 
						|
	for (my $i = 0; $i < scalar(@issue_ids2); $i += 3)
 | 
						|
	{
 | 
						|
		my $id = @issue_ids2[$i + 1];
 | 
						|
		@tmp{$id} = 1;
 | 
						|
	}
 | 
						|
	my @unique_issue_ids = keys(%tmp);
 | 
						|
 | 
						|
	$dbh->begin_work ();
 | 
						|
 | 
						|
	my $query = $dbh->prepare ("DELETE FROM ${QC}${prefix}issue_coderev${QC} WHERE ${QC}codeproid${QC}=? AND ${QC}coderev${QC}=?");
 | 
						|
	if (!$query || !$query->execute ($projectid, $revision))
 | 
						|
	{
 | 
						|
		my $errstr = $dbh->errstr();
 | 
						|
		if ($query) { $query->finish (); }
 | 
						|
		$dbh->rollback ();
 | 
						|
		return (-1, $errstr);
 | 
						|
	}
 | 
						|
	$query->finish ();
 | 
						|
 | 
						|
	for my $issue_id(@unique_issue_ids)
 | 
						|
	{
 | 
						|
		my $query = $dbh->prepare ("INSERT INTO ${QC}${prefix}issue_coderev${QC} (${QC}projectid${QC},${QC}issueid${QC},${QC}codeproid${QC},${QC}coderev${QC}) VALUES (?,?,?,?)");
 | 
						|
		if ($query)
 | 
						|
		{
 | 
						|
			# ignore errors
 | 
						|
			$query->execute ($projectid, $issue_id, $projectid, $revision);
 | 
						|
			$query->finish ();
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	$dbh->commit ();
 | 
						|
	return (0, undef);
 | 
						|
}
 | 
						|
 | 
						|
sub write_revprop_change_log
 | 
						|
{
 | 
						|
	my ($dbh, $prefix, $projectid, $revision, $userid, $propname, $action) = @_;
 | 
						|
 | 
						|
#+------+---------+-----------+---------------------------+---------------------+---------------+-----------------+
 | 
						|
#| id   | type    | projectid | message                   | createdon           | action        | userid          |
 | 
						|
#+------+---------+-----------+---------------------------+---------------------+---------------+-----------------+
 | 
						|
#| 1610 | code    | codepot   | svn,codepot,98,svn:log,M  | 2014-05-16 22:27:36 | revpropchange | hyunghwan.chung | 
 | 
						|
 | 
						|
	my $message = "svn,$projectid,$revision,$propname,$action";
 | 
						|
	my $createdon = strftime ('%Y-%m-%d %H:%M:%S', localtime());
 | 
						|
 | 
						|
	$dbh->begin_work ();
 | 
						|
 | 
						|
	my $query = $dbh->prepare ("INSERT INTO ${QC}${prefix}log${QC} (${QC}type${QC},${QC}projectid${QC},${QC}message${QC},${QC}createdon${QC},${QC}action${QC},${QC}userid${QC}) VALUES (?,?,?,?,?,?)");
 | 
						|
	if (!$query || !$query->execute ('code', $projectid, $message, $createdon, 'revpropchange', $userid))
 | 
						|
	{
 | 
						|
		my $errstr = $dbh->errstr();
 | 
						|
		if ($query) { $query->finish (); }
 | 
						|
		$dbh->rollback ();
 | 
						|
		return (-1, $errstr);
 | 
						|
	}
 | 
						|
 | 
						|
	$query->finish ();
 | 
						|
	$dbh->commit ();
 | 
						|
	return (0, undef);
 | 
						|
}
 | 
						|
 | 
						|
sub get_commit_message
 | 
						|
{
 | 
						|
	my $pool = SVN::Pool->new(undef);
 | 
						|
	my $svn = eval { SVN::Repos::open ($REPOFS, $pool) };
 | 
						|
	if (!defined($svn))
 | 
						|
	{
 | 
						|
		print (STDERR "Cannot open svn - $REPOFS\n");
 | 
						|
		return undef;
 | 
						|
	}
 | 
						|
 | 
						|
	my $fs = $svn->fs ();
 | 
						|
	if (!defined($fs))
 | 
						|
	{
 | 
						|
		print (STDERR "Cannot open fs - $REPOFS\n");
 | 
						|
		return undef;
 | 
						|
	}
 | 
						|
 | 
						|
	my $logmsg = $fs->revision_prop ($REV, 'svn:log');
 | 
						|
	return $logmsg;
 | 
						|
}
 | 
						|
 | 
						|
#------------------------------------------------------------
 | 
						|
# MAIN
 | 
						|
#------------------------------------------------------------
 | 
						|
 | 
						|
my $cfg = get_config ();
 | 
						|
if (!defined($cfg))
 | 
						|
{
 | 
						|
	print (STDERR "Cannot load codepot configuration file\n");
 | 
						|
	exit (1);
 | 
						|
}
 | 
						|
 | 
						|
my $dbh = open_database ($cfg);
 | 
						|
if (!defined($dbh))
 | 
						|
{
 | 
						|
	printf (STDERR "Cannot open database - %s\n", $DBI::errstr);
 | 
						|
	exit (1);
 | 
						|
}
 | 
						|
 | 
						|
my $raw_commit_message = get_commit_message();
 | 
						|
 | 
						|
find_issue_reference_in_commit_message ($dbh, $cfg->{database_prefix}, $REPOBASE, $REV, $raw_commit_message);
 | 
						|
write_revprop_change_log ($dbh, $cfg->{database_prefix}, $REPOBASE, $REV, $USER, $PROPNAME, $ACTION);
 | 
						|
close_database ($dbh);
 | 
						|
 | 
						|
exit (0);
 | 
						|
 |