10
8
# implied. See the License for the specific language governing
11
9
# rights and limitations under the License.
13
# The Original Code is the Bugzilla Bug Tracking System.
11
# The Original Code is the Bugzilla TraceParser Plugin.
15
13
# The Initial Developer of the Original Code is Canonical Ltd.
16
# Portions created by the Initial Developer are Copyright (C) 2009
17
# the Initial Developer. All Rights Reserved.
14
# Portions created by Canonical Ltd. are Copyright (C) 2009
15
# Canonical Ltd. All Rights Reserved.
20
18
# Max Kanat-Alexander <mkanat@bugzilla.org>
22
package TraceParser::Hooks;
20
package Bugzilla::Extension::TraceParser;
24
use base qw(Exporter);
22
use base qw(Bugzilla::Extension);
26
25
use Bugzilla::Constants;
27
26
use Bugzilla::Error;
28
28
use Bugzilla::Install::Util qw(indicate_progress);
29
use Bugzilla::User::Setting qw(add_setting);
29
30
use Bugzilla::Util qw(detaint_natural);
31
use TraceParser::Trace;
32
use Bugzilla::Extension::TraceParser::Trace;
34
35
use POSIX qw(ceil);
37
our $VERSION = '0.01';
44
39
use constant DEFAULT_POPULAR_LIMIT => 20;
48
my $bug = $params{bug};
41
sub bug_end_of_create {
42
my ($self, $args) = @_;
44
my $bug = $args->{bug};
49
45
my $comments = Bugzilla::Bug::GetComments($bug->id, 'oldest_to_newest',
50
46
'1970-01-01', $bug->creation_ts, 'raw');
51
47
my $comment = $comments->[0];
52
my $data = TraceParser::Trace->parse_from_text($comment->{body});
48
my $data = Bugzilla::Extension::TraceParser::Trace->parse_from_text($comment->{body});
54
my $trace = TraceParser::Trace->create(
50
my $trace = Bugzilla::Extension::TraceParser::Trace->create(
55
51
{ %$data, comment_id => $comment->{id} });
56
_check_duplicate_trace($trace, $bug, $comment);
52
_check_duplicate_trace($trace, $bug, $comment);
59
55
sub _check_duplicate_trace {
241
237
comment_added => $comment_added });
246
my ($bug, $timestamp) = @params{qw(bug timestamp)};
242
sub bug_end_of_update {
243
my ($self, $args) = @_;
245
my ($bug, $timestamp) = @$args{qw(bug timestamp)};
247
246
return if !$bug->{added_comments};
248
247
my $comments = Bugzilla::Bug::GetComments($bug->id, 'oldest_to_newest',
249
248
$bug->delta_ts, $timestamp, 1);
250
249
foreach my $comment (@$comments) {
251
my $data = TraceParser::Trace->parse_from_text($comment->{body});
250
my $data = Bugzilla::Extension::TraceParser::Trace->parse_from_text(
253
TraceParser::Trace->create({ %$data, comment_id => $comment->{id} });
253
Bugzilla::Extension::TraceParser::Trace->create(
254
{ %$data, comment_id => $comment->{id} });
258
sub bug_format_comment {
259
my ($self, $args) = @_;
261
my ($text, $bug, $regexes, $comment) = @$args{qw(text bug regexes comment)};
263
my ($trace) = @{ Bugzilla::Extension::TraceParser::Trace->match(
264
{ comment_id => $comment->{id} }) };
267
# $$text contains the wrapped text, and $comment contains the unwrapped
268
# text. To find the trace that we want from the DB, we need to use the
269
# unwrapped text. But to find the text that we need to replace, we
270
# need to use the wrapped text.
272
if ($comment->{already_wrapped}) {
273
$match_text = $trace->text;
276
my $stacktrace = Bugzilla::Extension::TraceParser::Trace->stacktrace_from_text($$text);
277
$match_text = $stacktrace->text;
280
$match_text = quotemeta($match_text);
282
my $template = Bugzilla->template_inner;
283
$template->process('trace/format.html.tmpl', { trace => $trace },
285
|| ThrowTemplateError($template->error);
286
# Make sure that replacements don't contain $1, $2, etc.
287
$replacement =~ s{\$}{\\\$};
288
push(@$regexes, { match => qr/$match_text/s, replace => $replacement });
291
sub db_schema_abstract_schema {
292
my ($self, $args) = @_;
296
my $schema = $args->{schema};
299
id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1,
301
comment_id => {TYPE => 'INT3', NOTNULL => 1,
302
REFERENCES => {TABLE => 'longdescs',
303
COLUMN => 'comment_id',
304
DELETE => 'CASCADE'}},
305
type => {TYPE => 'varchar(255)', NOTNULL => 1},
306
short_hash => {TYPE => 'char(22)'},
307
stack_hash => {TYPE => 'char(22)'},
308
trace_text => {TYPE => 'LONGTEXT', NOTNULL => 1},
309
quality => {TYPE => 'real', NOTNULL => 1},
312
trace_short_hash_idx => ['short_hash'],
313
trace_stack_hash_idx => ['stack_hash'],
314
trace_comment_id_idx => {TYPE => 'UNIQUE', FIELDS => ['comment_id']},
318
$schema->{trace_dup} = {
320
hash => {TYPE => 'char(22)', NOTNULL => 1},
321
identical => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0},
322
bug_id => {TYPE => 'INT3', NOTNULL => 1,
323
REFERENCES => {TABLE => 'bugs',
324
COLUMN => 'bug_id'}},
327
trace_dup_hash_idx => {TYPE => 'UNIQUE',
328
FIELDS => [qw(hash identical)]},
329
trace_bug_id_idx => ['bug_id'],
334
sub install_before_final_checks {
335
my ($self, $args) = @_;
337
if (!new Bugzilla::Group({ name => 'traceparser_edit' })) {
338
Bugzilla::Group->create({
339
name => 'traceparser_edit',
340
description => 'Can edit properties of traces',
344
add_setting('traceparser_show_traces',
345
['on', 'off'], 'off');
257
348
sub install_update_db {
293
384
$dbh->bz_start_transaction();
294
385
while (my $trace = shift @traces) {
295
TraceParser::Trace->create($trace);
386
Bugzilla::Extension::TraceParser::Trace->create($trace);
296
387
indicate_progress({ current => $count++, total => $total_traces,
299
390
$dbh->bz_commit_transaction();
304
my ($text, $bug, $regexes, $comment) = @params{qw(text bug regexes comment)};
306
my ($trace) = @{ TraceParser::Trace->match({ comment_id => $comment->{id} }) };
309
# $$text contains the wrapped text, and $comment contains the unwrapped
310
# text. To find the trace that we want from the DB, we need to use the
311
# unwrapped text. But to find the text that we need to replace, we
312
# need to use the wrapped text.
314
if ($comment->{already_wrapped}) {
315
$match_text = $trace->text;
318
my $stacktrace = TraceParser::Trace->stacktrace_from_text($$text);
319
$match_text = $stacktrace->text;
322
$match_text = quotemeta($match_text);
324
my $template = Bugzilla->template_inner;
325
$template->process('trace/format.html.tmpl', { trace => $trace },
327
|| ThrowTemplateError($template->error);
328
# Make sure that replacements don't contain $1, $2, etc.
329
$replacement =~ s{\$}{\\\$};
330
push(@$regexes, { match => qr/$match_text/s, replace => $replacement });
335
my ($vars, $page) = @params{qw(vars page_id)};
393
sub page_before_template {
394
my ($self, $args) = @_;
396
my ($vars, $page) = @$args{qw(vars page_id)};
336
397
if ($page =~ /^trace\./) {
337
398
_page_trace($vars);