From fdfa5ecaa09240449eb34ffe7e9ec4c0405f1ead Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 22 Jan 2016 18:12:06 +0000 Subject: [PATCH] wrote code to corelate issues and code revisions. changed the code revision view to show corelated issues --- codepot/etc/codepot.mysql | 27 +++- codepot/etc/post-commit.in | 54 ++++++- codepot/etc/post-revprop-change.in | 74 +++++++++- codepot/src/codepot/controllers/code.php | 25 ++-- codepot/src/codepot/models/Makefile.am | 2 +- codepot/src/codepot/models/Makefile.in | 2 +- .../{codereviewmodel.php => codemodel.php} | 28 +++- codepot/src/codepot/views/code_blame.php | 2 +- codepot/src/codepot/views/code_diff.php | 2 +- codepot/src/codepot/views/code_file.php | 2 +- codepot/src/codepot/views/code_folder.php | 2 +- codepot/src/codepot/views/code_revision.php | 36 ++++- codepot/src/codepot/views/file_show.php | 4 +- codepot/src/codepot/views/issue_show.php | 29 ++-- codepot/src/codepot/views/wiki_edit.php | 2 +- codepot/src/codepot/views/wiki_editx.php | 9 +- codepot/src/codepot/views/wiki_show.php | 2 +- codepot/src/css/code.css | 39 ++--- codepot/src/css/common.css | 137 +++++++++++++++++- codepot/src/css/file.css | 7 - codepot/src/css/issue.css | 133 ++--------------- codepot/src/css/wiki.css | 7 - 22 files changed, 418 insertions(+), 207 deletions(-) rename codepot/src/codepot/models/{codereviewmodel.php => codemodel.php} (82%) diff --git a/codepot/etc/codepot.mysql b/codepot/etc/codepot.mysql index a7f904b5..cba4d6b6 100644 --- a/codepot/etc/codepot.mysql +++ b/codepot/etc/codepot.mysql @@ -142,7 +142,7 @@ CREATE TABLE issue_change ( PRIMARY KEY (projectid, id, sno), KEY issue_update_time (projectid, id, updatedon), - CONSTRAINT issue_update_id FOREIGN KEY (projectid,id) REFERENCES issue(projectid,id) + CONSTRAINT issue_change_id FOREIGN KEY (projectid,id) REFERENCES issue(projectid,id) ON DELETE RESTRICT ON UPDATE CASCADE ) charset=utf8 engine=InnoDB; @@ -168,6 +168,31 @@ CREATE TABLE issue_change_file_list ( ON DELETE RESTRICT ON UPDATE CASCADE ) charset=utf8 engine=InnoDB; +CREATE TABLE issue_coderev ( + projectid VARCHAR(32) NOT NULL, + issueid BIGINT NOT NULL, + + codeproid VARCHAR(32) NOT NULL, + coderev VARCHAR(64) NOT NULL, -- git commit id is 40 characters. subversion revision is a number. + + UNIQUE KEY issue_coderev_uid(projectid, issueid, codeproid, coderev), + + KEY issue_coderev_codekey (codeproid, coderev), + KEY issue_coderev_issuekey (projectid, issueid), + + CONSTRAINT issue_coderev_projectid FOREIGN KEY (projectid) REFERENCES project(id) + ON DELETE RESTRICT ON UPDATE CASCADE, + + CONSTRAINT issue_coderev_codeproid FOREIGN KEY (codeproid) REFERENCES project(id) + ON DELETE RESTRICT ON UPDATE CASCADE + + -- Commit message is typypicall free text. Its issue reference could be error-prone. + -- So i won't have this constraint enforced. + -- CONSTRAINT issue_coderev_issueid FOREIGN KEY (projectid,issueid) REFERENCES issue(projectid,id) + -- ON DELETE RESTRICT ON UPDATE CASCADE + +) charset=utf8 engine=InnoDB; + CREATE TABLE file ( projectid VARCHAR(32) NOT NULL, name VARCHAR(255) NOT NULL, diff --git a/codepot/etc/post-commit.in b/codepot/etc/post-commit.in index c3e14178..f5f69741 100644 --- a/codepot/etc/post-commit.in +++ b/codepot/etc/post-commit.in @@ -109,6 +109,45 @@ sub close_database $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 unique issue ids in the findings. + my %tmp; + @tmp{@issue_ids}=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_commit_log { my ($dbh, $prefix, $projectid, $revision, $userid) = @_; @@ -136,7 +175,7 @@ sub write_commit_log if (!$query || !$query->execute ('code', $projectid, $message, 'commit', $userid)) { my $errstr = $dbh->errstr(); - $query->finish (); + if ($query) { $query->finish (); } $dbh->rollback (); return (-1, $errstr); } @@ -185,8 +224,8 @@ sub get_commit_message return undef; } - my $author = $fs->revision_prop ($REV, 'svn:log'); - return $author; + my $logmsg = $fs->revision_prop ($REV, 'svn:log'); + return $logmsg; } @@ -317,6 +356,7 @@ sub email_message_to_project_members my $query = $dbh->prepare ("SELECT ${QC}userid${QC} FROM ${QC}${prefix}project_membership${QC} WHERE ${QC}projectid${QC}=?"); if (!$query || !$query->execute ($projectid)) { + if ($query) { $query->finish (); } return (-1, $dbh->errstr()); } @@ -408,6 +448,9 @@ if (!defined($dbh)) 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_commit_log ($dbh, $cfg->{database_prefix}, $REPOBASE, $REV, $AUTHOR); if (lc($cfg->{commit_notification}) eq 'yes') @@ -424,10 +467,9 @@ if (lc($cfg->{commit_notification}) eq 'yes') $commit_message = format_commit_url($cfg->{commit_notification_url}, $REPOBASE, $AUTHOR, $REV); } - my $m = get_commit_message (); - if (defined($m)) + if (defined($raw_commit_message)) { - $commit_message = $commit_message . "\n" . $m; + $commit_message = $commit_message . "\n" . $raw_commit_message; } diff --git a/codepot/etc/post-revprop-change.in b/codepot/etc/post-revprop-change.in index c9e25be9..932b6bf2 100644 --- a/codepot/etc/post-revprop-change.in +++ b/codepot/etc/post-revprop-change.in @@ -7,9 +7,13 @@ 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 $REPO = $ARGV[0]; -my $REPOBASE = basename($REPO); +my $REPOFS = $ARGV[0]; +my $REPOBASE = basename($REPOFS); my $REV = $ARGV[1]; my $USER = $ARGV[2]; my $PROPNAME = $ARGV[3]; @@ -88,6 +92,46 @@ sub close_database $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 unique issue ids in the findings. + my %tmp; + @tmp{@issue_ids}=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) = @_; @@ -106,7 +150,7 @@ sub write_revprop_change_log if (!$query || !$query->execute ('code', $projectid, $message, $createdon, 'revpropchange', $userid)) { my $errstr = $dbh->errstr(); - $query->finish (); + if ($query) { $query->finish (); } $dbh->rollback (); return (-1, $errstr); } @@ -116,6 +160,27 @@ sub write_revprop_change_log 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 #------------------------------------------------------------ @@ -134,6 +199,9 @@ if (!defined($dbh)) 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); diff --git a/codepot/src/codepot/controllers/code.php b/codepot/src/codepot/controllers/code.php index d179e3a0..fc38dd13 100644 --- a/codepot/src/codepot/controllers/code.php +++ b/codepot/src/codepot/controllers/code.php @@ -724,7 +724,7 @@ class Code extends Controller { $this->load->model ('ProjectModel', 'projects'); $this->load->model ('SubversionModel', 'subversion'); - $this->load->model ('CodeReviewModel', 'code_review'); + $this->load->model ('CodeModel', 'code'); $login = $this->login->getUser (); $revision_saved = -1; @@ -759,10 +759,10 @@ class Code extends Controller } else { - $review_sno = $this->code_review->insertReview ($projectid, $rev, $login['id'], $review_comment); + $review_sno = $this->code->insertReview ($projectid, $rev, $login['id'], $review_comment); if ($review_sno === FALSE) { - $status = 'error - ' . $this->code_review->getErrorMessage(); + $status = 'error - ' . $this->code->getErrorMessage(); } else { @@ -792,7 +792,7 @@ class Code extends Controller { $this->load->model ('ProjectModel', 'projects'); $this->load->model ('SubversionModel', 'subversion'); - $this->load->model ('CodeReviewModel', 'code_review'); + $this->load->model ('CodeModel', 'code'); $login = $this->login->getUser (); $revision_saved = -1; @@ -832,9 +832,9 @@ class Code extends Controller } else { - if ($this->code_review->updateReview ($projectid, $rev, (integer)$review_no, $login['id'], $review_comment, TRUE) === FALSE) + if ($this->code->updateReview ($projectid, $rev, (integer)$review_no, $login['id'], $review_comment, TRUE) === FALSE) { - $status = 'error - ' . $this->code_review->getErrorMessage(); + $status = 'error - ' . $this->code->getErrorMessage(); } else { @@ -993,8 +993,8 @@ class Code extends Controller { $this->load->model ('ProjectModel', 'projects'); $this->load->model ('SubversionModel', 'subversion'); - $this->load->model ('CodeReviewModel', 'code_review'); - + $this->load->model ('CodeModel', 'code'); + $login = $this->login->getUser (); if (CODEPOT_SIGNIN_COMPULSORY && $login['id'] == '') redirect ("main/signin/" . $this->converter->AsciiTohex(current_url())); @@ -1048,7 +1048,11 @@ class Code extends Controller if (array_key_exists('rev', $h)) $r_rev = $h['rev']; } } - $reviews = $this->code_review->getReviews ($projectid, $r_rev); + + $related_issues = $this->code->getRelatedIssues ($projectid, $r_rev); + if ($related_issues == FALSE) $related_issues = array(); + + $reviews = $this->code->getReviews ($projectid, $r_rev); if ($reviews === FALSE) { $data['project'] = $project; @@ -1122,7 +1126,8 @@ class Code extends Controller $data['headpath'] = $path; $data['file'] = $file; $data['reviews'] = $reviews; - + $data['related_issues'] = $related_issues; + $data['revision'] = $rev; $data['prev_revision'] = $prev_revision; $data['next_revision'] = $this->subversion->getNextRev ($projectid, $path, $rev); diff --git a/codepot/src/codepot/models/Makefile.am b/codepot/src/codepot/models/Makefile.am index 4e9664ff..4b6b1658 100644 --- a/codepot/src/codepot/models/Makefile.am +++ b/codepot/src/codepot/models/Makefile.am @@ -1,6 +1,6 @@ wwwdir=$(WWWDIR)/codepot/models www_DATA = \ - codereviewmodel.php \ + codemodel.php \ dbloginmodel.php \ filemodel.php \ index.html \ diff --git a/codepot/src/codepot/models/Makefile.in b/codepot/src/codepot/models/Makefile.in index db583a2b..0b744f91 100644 --- a/codepot/src/codepot/models/Makefile.in +++ b/codepot/src/codepot/models/Makefile.in @@ -145,7 +145,7 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ wwwdir = $(WWWDIR)/codepot/models www_DATA = \ - codereviewmodel.php \ + codemodel.php \ dbloginmodel.php \ filemodel.php \ index.html \ diff --git a/codepot/src/codepot/models/codereviewmodel.php b/codepot/src/codepot/models/codemodel.php similarity index 82% rename from codepot/src/codepot/models/codereviewmodel.php rename to codepot/src/codepot/models/codemodel.php index 929f4a65..30629db8 100644 --- a/codepot/src/codepot/models/codereviewmodel.php +++ b/codepot/src/codepot/models/codemodel.php @@ -1,6 +1,6 @@ errmsg; } - function CodeReviewModel () + function CodeModel () { parent::Model (); $this->load->database (); } + function getRelatedIssues ($projectid, $revision) + { + $this->db->trans_begin (); + + $this->db->from ('issue'); + $this->db->join ('issue_coderev', 'issue.projectid = issue_coderev.projectid AND issue.id = issue_coderev.issueid'); + //$this->db->where ('issue_coderev.projectid', (string)$projectid); + $this->db->where ('issue_coderev.codeproid', (string)$projectid); + $this->db->where ('issue_coderev.coderev', $revision); + $this->db->order_by ('issue.projectid ASC'); + $this->db->order_by ('issue_coderev.issueid ASC'); + $this->db->select ('issue.projectid, issue_coderev.issueid, issue.summary, issue.type, issue.status, issue.priority, issue.owner'); + $query = $this->db->get (); + if ($this->db->trans_status() === FALSE) + { + $this->errmsg = $this->db->_error_message(); + $this->db->trans_rollback (); + return FALSE; + } + + $this->db->trans_commit (); + return $query->result(); + } + function getReviews ($projectid, $revision) { $this->db->trans_begin (); diff --git a/codepot/src/codepot/views/code_blame.php b/codepot/src/codepot/views/code_blame.php index c4e39922..a546ffc9 100644 --- a/codepot/src/codepot/views/code_blame.php +++ b/codepot/src/codepot/views/code_blame.php @@ -255,7 +255,7 @@ $this->load->view (
-
+ -
+ -
+ -
+ -
+ + '; + } + ?> + +
diff --git a/codepot/src/codepot/views/file_show.php b/codepot/src/codepot/views/file_show.php index 0e6c11ac..27019f86 100644 --- a/codepot/src/codepot/views/file_show.php +++ b/codepot/src/codepot/views/file_show.php @@ -613,7 +613,7 @@ $this->load->view (
lang->line('Metadata')?>
-
+