From ed3e015a1c21061ed9f30cfc3fe3c3e83c0d2fb1 Mon Sep 17 00:00:00 2001 From: Tiago Mello Date: Mon, 20 Dec 2010 20:49:10 -0200 Subject: Bug 593539: Refactor See Also to use separate modules for each type of URL r/a=mkanat --- Bugzilla/Bug.pm | 192 +++++++------------------------------- Bugzilla/BugUrl.pm | 173 ++++++++++++++++++++++++++++++++++ Bugzilla/BugUrl/Bugzilla.pm | 61 ++++++++++++ Bugzilla/BugUrl/Bugzilla/Local.pm | 105 +++++++++++++++++++++ Bugzilla/BugUrl/Debian.pm | 62 ++++++++++++ Bugzilla/BugUrl/Google.pm | 64 +++++++++++++ Bugzilla/BugUrl/Launchpad.pm | 58 ++++++++++++ Bugzilla/Install/DB.pm | 3 + 8 files changed, 558 insertions(+), 160 deletions(-) create mode 100644 Bugzilla/BugUrl.pm create mode 100644 Bugzilla/BugUrl/Bugzilla.pm create mode 100644 Bugzilla/BugUrl/Bugzilla/Local.pm create mode 100644 Bugzilla/BugUrl/Debian.pm create mode 100644 Bugzilla/BugUrl/Google.pm create mode 100644 Bugzilla/BugUrl/Launchpad.pm (limited to 'Bugzilla') diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index 9d41d5c7e..fd0111578 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -49,6 +49,7 @@ use Bugzilla::Component; use Bugzilla::Group; use Bugzilla::Status; use Bugzilla::Comment; +use Bugzilla::BugUrl; use List::MoreUtils qw(firstidx uniq); use List::Util qw(min max first); @@ -930,6 +931,14 @@ sub update { } # See Also + foreach my $field_values (@{ $self->{added_see_also} || [] }) { + my $class = delete $field_values->{class}; + $class->insert_create_data($field_values); + push @{ $self->see_also }, $field_values->{value}; + } + + delete $self->{added_see_also}; + my ($removed_see, $added_see) = diff_arrays($old_bug->see_also, $self->see_also); @@ -938,19 +947,13 @@ sub update { . $dbh->sql_in('value', [('?') x @$removed_see]), undef, $self->id, @$removed_see); } - foreach my $url (@$added_see) { - $dbh->do('INSERT INTO bug_see_also (bug_id, value) VALUES (?,?)', - undef, $self->id, $url); - } + # If any changes were found, record it in the activity log if (scalar @$removed_see || scalar @$added_see) { $changes->{see_also} = [join(', ', @$removed_see), join(', ', @$added_see)]; } - # Call update for the referenced bugs. - $_->update() foreach @{ $self->{see_also_update} || [] }; - # Log bugs_activity items # XXX Eventually, when bugs_activity is able to track the dupe_id, # this code should go below the duplicates-table-updating code below. @@ -1193,9 +1196,9 @@ sub send_changes { } # Sending emails for the referenced bugs. - foreach my $ref_bug (@{ $self->{see_also_update} || [] }) { + foreach my $ref_bug_id (uniq @{ $self->{see_also_changes} || [] }) { _send_bugmail({ forced => { changer => $user }, - id => $ref_bug->id }, $vars); + id => $ref_bug_id }, $vars); } } @@ -2787,173 +2790,42 @@ sub remove_group { } sub add_see_also { - my ($self, $input, $skip_recursion) = @_; + my ($self, $input) = @_; $input = trim($input); - if (!$input) { - ThrowCodeError('param_required', - { function => 'add_see_also', param => '$input' }); - } - - # If a bug id/alias has been taken, then treat it - # as a link to the local Bugzilla. - my $local_bug_uri = correct_urlbase() . "show_bug.cgi?id="; - if ($input =~ m/^\w+$/) { - $input = $local_bug_uri . $input; - } - - # We assume that the URL is an HTTP URL if there is no (something):// - # in front. - my $uri = new URI($input); - if (!$uri->scheme) { - # This works better than setting $uri->scheme('http'), because - # that creates URLs like "http:domain.com" and doesn't properly - # differentiate the path from the domain. - $uri = new URI("http://$input"); - } - elsif ($uri->scheme ne 'http' && $uri->scheme ne 'https') { - ThrowUserError('bug_url_invalid', { url => $input, reason => 'http' }); - } - - # This stops the following edge cases from being accepted: - # * show_bug.cgi?id=1 - # * /show_bug.cgi?id=1 - # * http:///show_bug.cgi?id=1 - if (!$uri->authority or $uri->path !~ m{/}) { - ThrowUserError('bug_url_invalid', - { url => $input, reason => 'path_only' }); - } - - my $result; - # Launchpad URLs - if ($uri->authority =~ /launchpad.net$/) { - # Launchpad bug URLs can look like various things: - # https://bugs.launchpad.net/ubuntu/+bug/1234 - # https://launchpad.net/bugs/1234 - # All variations end with either "/bugs/1234" or "/+bug/1234" - if ($uri->path =~ m|bugs?/(\d+)$|) { - # This is the shortest standard URL form for Launchpad bugs, - # and so we reduce all URLs to this. - $result = "https://launchpad.net/bugs/$1"; - } - else { - ThrowUserError('bug_url_invalid', - { url => $input, reason => 'id' }); - } - } - # Google Code URLs - elsif ($uri->authority =~ /^code.google.com$/i) { - # Google Code URLs only have one form: - # http(s)://code.google.com/p/PROJECT_NAME/issues/detail?id=1234 - my $project_name; - if ($uri->path =~ m|^/p/([^/]+)/issues/detail$|) { - $project_name = $1; - } else { - ThrowUserError('bug_url_invalid', - { url => $input }); - } - my $bug_id = $uri->query_param('id'); - detaint_natural($bug_id); - if (!$bug_id) { - ThrowUserError('bug_url_invalid', - { url => $input, reason => 'id' }); - } - # While Google Code URLs can be either HTTP or HTTPS, - # always go with the HTTP scheme, as that's the default. - $result = "http://code.google.com/p/" . $project_name . - "/issues/detail?id=" . $bug_id; - } - # Debian BTS URLs - elsif ($uri->authority =~ /^bugs.debian.org$/i) { - # Debian BTS URLs can look like various things: - # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1234 - # http://bugs.debian.org/1234 - my $bug_id; - if ($uri->path =~ m|^/(\d+)$|) { - $bug_id = $1; - } - elsif ($uri->path =~ /bugreport\.cgi$/) { - $bug_id = $uri->query_param('bug'); - detaint_natural($bug_id); - } - if (!$bug_id) { - ThrowUserError('bug_url_invalid', - { url => $input, reason => 'id' }); - } - # This is the shortest standard URL form for Debian BTS URLs, - # and so we reduce all URLs to this. - $result = "http://bugs.debian.org/" . $bug_id; - } - # Bugzilla URLs - else { - if ($uri->path !~ /show_bug\.cgi$/) { - ThrowUserError('bug_url_invalid', - { url => $input, reason => 'show_bug' }); - } - - my $bug_id = $uri->query_param('id'); - # We don't currently allow aliases, because we can't check to see - # if somebody's putting both an alias link and a numeric ID link. - # When we start validating the URL by accessing the other Bugzilla, - # we can allow aliases. - detaint_natural($bug_id); - if (!$bug_id) { - ThrowUserError('bug_url_invalid', - { url => $input, reason => 'id' }); - } + my ($class, $uri) = Bugzilla::BugUrl->class_for($input); - # Make sure that "id" is the only query parameter. - $uri->query("id=$bug_id"); - # And remove any # part if there is one. - $uri->fragment(undef); - my $uri_canonical = $uri->canonical; - $result = $uri_canonical->as_string; - - # If this is a link to a local bug (treating the domain - # case-insensitively and ignoring http(s)://), then also update - # the other bug to point at this one. - my $canonical_local = URI->new($local_bug_uri)->canonical; - if (!$skip_recursion - and $canonical_local->authority eq $uri_canonical->authority - and $canonical_local->path eq $uri_canonical->path) - { - my $ref_bug = Bugzilla::Bug->check($bug_id); - if ($ref_bug->id == $self->id) { - ThrowUserError('see_also_self_reference'); - } - - my $product = $ref_bug->product_obj; - if (!Bugzilla->user->can_edit_product($product->id)) { - ThrowUserError("product_edit_denied", - { product => $product->name }); - } - - my $ref_input = $local_bug_uri . $self->id; - if (!grep($ref_input, @{ $ref_bug->see_also })) { - $ref_bug->add_see_also($ref_input, 'skip recursion'); - push @{ $self->{see_also_update} }, $ref_bug; - } - } + my $params = { value => $uri, bug_id => $self }; + $class->check_required_create_fields($params); - } + my $field_values = $class->run_create_validators($params); + $uri = $field_values->{value}; + $field_values->{value} = $uri->as_string; + $field_values->{class} = $class; - if (length($result) > MAX_BUG_URL_LENGTH) { - ThrowUserError('bug_url_too_long', { url => $result }); + # If this is a link to a local bug then save the + # ref bug id for sending changes email. + if ($class->isa('Bugzilla::BugUrl::Bugzilla::Local')) { + my $ref_bug = $field_values->{ref_bug}; + my $self_url = $class->local_uri . $self->id; + push @{ $self->{see_also_changes} }, $ref_bug->id + if !grep { $_ eq $self_url } @{ $ref_bug->see_also }; } # We only add the new URI if it hasn't been added yet. URIs are # case-sensitive, but most of our DBs are case-insensitive, so we do # this check case-insensitively. - if (!grep { lc($_) eq lc($result) } @{ $self->see_also }) { + my $value = $uri->as_string; + if (!grep { lc($_) eq lc($value) } @{ $self->see_also }) { my $privs; - my $can = $self->check_can_change_field('see_also', '', $result, \$privs); + my $can = $self->check_can_change_field('see_also', '', $value, \$privs); if (!$can) { ThrowUserError('illegal_change', { field => 'see_also', - newvalue => $result, + newvalue => $value, privs => $privs }); } - push(@{ $self->see_also }, $result); + push @{ $self->{added_see_also} }, $field_values; } } diff --git a/Bugzilla/BugUrl.pm b/Bugzilla/BugUrl.pm new file mode 100644 index 000000000..521ee8193 --- /dev/null +++ b/Bugzilla/BugUrl.pm @@ -0,0 +1,173 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Tiago Mello +# Portions created by Tiago Mello are Copyright (C) 2010 +# Tiago Mello. All Rights Reserved. +# +# Contributor(s): Tiago Mello + +package Bugzilla::BugUrl; +use strict; +use base qw(Bugzilla::Object); + +use Bugzilla::Util; +use Bugzilla::Error; +use Bugzilla::Constants; + +use URI::QueryParam; + +############################### +#### Initialization #### +############################### + +use constant DB_TABLE => 'bug_see_also'; +use constant NAME_FIELD => 'value'; +use constant LIST_ORDER => 'id'; + +use constant DB_COLUMNS => qw( + id + bug_id + value +); + +# This must be strings with the names of the validations, +# instead of coderefs, because subclasses override these +# validators with their own. +use constant VALIDATORS => { + value => '_check_value', + bug_id => '_check_bug_id', +}; + +# This is the order we go through all of subclasses and +# pick the first one that should handle the url. New +# subclasses should be added at the end of the list. +use constant SUB_CLASSES => qw( + Bugzilla::BugUrl::Bugzilla::Local + Bugzilla::BugUrl::Bugzilla + Bugzilla::BugUrl::Launchpad + Bugzilla::BugUrl::Google + Bugzilla::BugUrl::Debian +); + +############################### +#### Methods #### +############################### + +sub new { + my $class = shift; + my $param = shift; + + if (ref $param) { + my $bug_id = $param->{bug_id}; + my $name = $param->{name} || $param->{value}; + if (!defined $bug_id) { + ThrowCodeError('bad_arg', + { argument => 'bug_id', + function => "${class}::new" }); + } + if (!defined $name) { + ThrowCodeError('bad_arg', + { argument => 'name', + function => "${class}::new" }); + } + + my $condition = 'bug_id = ? AND value = ?'; + my @values = ($bug_id, $name); + $param = { condition => $condition, values => \@values }; + } + + unshift @_, $param; + return $class->SUPER::new(@_); +} + +# This is an abstract method. It must be overridden +# in every subclass. +sub should_handle { + my ($class, $input) = @_; + ThrowCodeError('unknown_method', + { method => "${class}::should_handle" }); +} + +sub class_for { + my ($class, $value) = @_; + + my $uri = URI->new($value); + foreach my $subclass ($class->SUB_CLASSES) { + eval "use $subclass"; + die $@ if $@; + return wantarray ? ($subclass, $uri) : $subclass + if $subclass->should_handle($uri); + } + + ThrowUserError('bug_url_invalid', { url => $value, + reason => 'show_bug' }); +} + +sub _check_bug_id { + my ($class, $bug_id) = @_; + + my $bug; + if (blessed $bug_id) { + # We got a bug object passed in, use it + $bug = $bug_id; + $bug->check_is_visible; + } + else { + # We got a bug id passed in, check it and get the bug object + $bug = Bugzilla::Bug->check({ id => $bug_id }); + } + + return $bug->id; +} + +sub _check_value { + my ($class, $uri) = @_; + + my $value = $uri->as_string; + + if (!$value) { + ThrowCodeError('param_required', + { function => 'add_see_also', param => '$value' }); + } + + # We assume that the URL is an HTTP URL if there is no (something):// + # in front. + if (!$uri->scheme) { + # This works better than setting $uri->scheme('http'), because + # that creates URLs like "http:domain.com" and doesn't properly + # differentiate the path from the domain. + $uri = new URI("http://$value"); + } + elsif ($uri->scheme ne 'http' && $uri->scheme ne 'https') { + ThrowUserError('bug_url_invalid', { url => $value, reason => 'http' }); + } + + # This stops the following edge cases from being accepted: + # * show_bug.cgi?id=1 + # * /show_bug.cgi?id=1 + # * http:///show_bug.cgi?id=1 + if (!$uri->authority or $uri->path !~ m{/}) { + ThrowUserError('bug_url_invalid', + { url => $value, reason => 'path_only' }); + } + + if (length($uri->path) > MAX_BUG_URL_LENGTH) { + ThrowUserError('bug_url_too_long', { url => $uri->path }); + } + + return $uri; +} + +1; diff --git a/Bugzilla/BugUrl/Bugzilla.pm b/Bugzilla/BugUrl/Bugzilla.pm new file mode 100644 index 000000000..3957afc9d --- /dev/null +++ b/Bugzilla/BugUrl/Bugzilla.pm @@ -0,0 +1,61 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Tiago Mello +# Portions created by Tiago Mello are Copyright (C) 2010 +# Tiago Mello. All Rights Reserved. +# +# Contributor(s): Tiago Mello + +package Bugzilla::BugUrl::Bugzilla; +use strict; +use base qw(Bugzilla::BugUrl); + +use Bugzilla::Error; +use Bugzilla::Util; + +############################### +#### Methods #### +############################### + +sub should_handle { + my ($class, $uri) = @_; + return ($uri->path =~ /show_bug\.cgi$/) ? 1 : 0; +} + +sub _check_value { + my ($class, $uri) = @_; + + $uri = $class->SUPER::_check_value($uri); + + my $bug_id = $uri->query_param('id'); + # We don't currently allow aliases, because we can't check to see + # if somebody's putting both an alias link and a numeric ID link. + # When we start validating the URL by accessing the other Bugzilla, + # we can allow aliases. + detaint_natural($bug_id); + if (!$bug_id) { + my $value = $uri->as_string; + ThrowUserError('bug_url_invalid', { url => $value, reason => 'id' }); + } + + # Make sure that "id" is the only query parameter. + $uri->query("id=$bug_id"); + # And remove any # part if there is one. + $uri->fragment(undef); + + return $uri; +} + +1; diff --git a/Bugzilla/BugUrl/Bugzilla/Local.pm b/Bugzilla/BugUrl/Bugzilla/Local.pm new file mode 100644 index 000000000..22812d085 --- /dev/null +++ b/Bugzilla/BugUrl/Bugzilla/Local.pm @@ -0,0 +1,105 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Tiago Mello +# Portions created by Tiago Mello are Copyright (C) 2010 +# Tiago Mello. All Rights Reserved. +# +# Contributor(s): Tiago Mello + +package Bugzilla::BugUrl::Bugzilla::Local; +use strict; +use base qw(Bugzilla::BugUrl::Bugzilla); + +use Bugzilla::Error; +use Bugzilla::Util; + +############################### +#### Initialization #### +############################### + +use constant VALIDATOR_DEPENDENCIES => { + value => ['bug_id'], +}; + +############################### +#### Methods #### +############################### + +sub insert_create_data { + my ($class, $field_values) = @_; + + my $ref_bug = delete $field_values->{ref_bug}; + my $url = $class->local_uri . $field_values->{bug_id}; + my $bug_url = $class->SUPER::insert_create_data($field_values); + + # Check if the ref bug has already the url and then, + # update the ref bug to point to the current bug. + if (!grep { $_ eq $url } @{ $ref_bug->see_also }) { + $class->SUPER::insert_create_data( + { value => $url, bug_id => $ref_bug->id } ); + } + + return $bug_url; +} + +sub should_handle { + my ($class, $uri) = @_; + + return $uri->as_string =~ m/^\w+$/ ? 1 : 0; + + my $canonical_local = URI->new($class->_local_uri)->canonical; + + # Treating the domain case-insensitively and ignoring http(s):// + return ($canonical_local->authority eq $uri->canonical->authority + and $canonical_local->path eq $uri->canonical->path) ? 1 : 0; +} + +sub _check_value { + my ($class, $uri, undef, $params) = @_; + + # At this point we are going to treat any word as a + # bug id/alias to the local Bugzilla. + my $value = $uri->as_string; + if ($value =~ m/^\w+$/) { + $uri = new URI($class->local_uri . $value); + } else { + # It's not a word, then we have to check + # if it's a valid Bugzilla url. + $uri = $class->SUPER::_check_value($uri); + } + + my $ref_bug_id = $uri->query_param('id'); + my $ref_bug = Bugzilla::Bug->check($ref_bug_id); + my $self_bug_id = $params->{bug_id}; + $params->{ref_bug} = $ref_bug; + + if ($ref_bug->id == $self_bug_id) { + ThrowUserError('see_also_self_reference'); + } + + my $product = $ref_bug->product_obj; + if (!Bugzilla->user->can_edit_product($product->id)) { + ThrowUserError("product_edit_denied", + { product => $product->name }); + } + + return $uri; +} + +sub local_uri { + return correct_urlbase() . "show_bug.cgi?id="; +} + +1; diff --git a/Bugzilla/BugUrl/Debian.pm b/Bugzilla/BugUrl/Debian.pm new file mode 100644 index 000000000..90d61a69a --- /dev/null +++ b/Bugzilla/BugUrl/Debian.pm @@ -0,0 +1,62 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Tiago Mello +# Portions created by Tiago Mello are Copyright (C) 2010 +# Tiago Mello. All Rights Reserved. +# +# Contributor(s): Tiago Mello + +package Bugzilla::BugUrl::Debian; +use strict; +use base qw(Bugzilla::BugUrl); + +use Bugzilla::Error; +use Bugzilla::Util; + +############################### +#### Methods #### +############################### + +sub should_handle { + my ($class, $uri) = @_; + return ($uri->authority =~ /^bugs.debian.org$/i) ? 1 : 0; +} + +sub _check_value { + my $class = shift; + + my $uri = $class->SUPER::_check_value(@_); + + # Debian BTS URLs can look like various things: + # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1234 + # http://bugs.debian.org/1234 + my $bug_id; + if ($uri->path =~ m|^/(\d+)$|) { + $bug_id = $1; + } + elsif ($uri->path =~ /bugreport\.cgi$/) { + $bug_id = $uri->query_param('bug'); + detaint_natural($bug_id); + } + if (!$bug_id) { + ThrowUserError('bug_url_invalid', + { url => $uri->path, reason => 'id' }); + } + # This is the shortest standard URL form for Debian BTS URLs, + # and so we reduce all URLs to this. + return new URI("http://bugs.debian.org/" . $bug_id); +} + +1; diff --git a/Bugzilla/BugUrl/Google.pm b/Bugzilla/BugUrl/Google.pm new file mode 100644 index 000000000..4f6321e74 --- /dev/null +++ b/Bugzilla/BugUrl/Google.pm @@ -0,0 +1,64 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Tiago Mello +# Portions created by Tiago Mello are Copyright (C) 2010 +# Tiago Mello. All Rights Reserved. +# +# Contributor(s): Tiago Mello + +package Bugzilla::BugUrl::Google; +use strict; +use base qw(Bugzilla::BugUrl); + +use Bugzilla::Error; +use Bugzilla::Util; + +############################### +#### Methods #### +############################### + +sub should_handle { + my ($class, $uri) = @_; + return ($uri->authority =~ /^code.google.com$/i) ? 1 : 0; +} + +sub _check_value { + my ($class, $uri) = @_; + + $uri = $class->SUPER::_check_value($uri); + + my $value = $uri->as_string; + # Google Code URLs only have one form: + # http(s)://code.google.com/p/PROJECT_NAME/issues/detail?id=1234 + my $project_name; + if ($uri->path =~ m|^/p/([^/]+)/issues/detail$|) { + $project_name = $1; + } else { + ThrowUserError('bug_url_invalid', { url => $value }); + } + my $bug_id = $uri->query_param('id'); + detaint_natural($bug_id); + if (!$bug_id) { + ThrowUserError('bug_url_invalid', { url => $value, reason => 'id' }); + } + # While Google Code URLs can be either HTTP or HTTPS, + # always go with the HTTP scheme, as that's the default. + $value = "http://code.google.com/p/" . $project_name . + "/issues/detail?id=" . $bug_id; + + return new URI($value); +} + +1; diff --git a/Bugzilla/BugUrl/Launchpad.pm b/Bugzilla/BugUrl/Launchpad.pm new file mode 100644 index 000000000..bb16b3b30 --- /dev/null +++ b/Bugzilla/BugUrl/Launchpad.pm @@ -0,0 +1,58 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Tiago Mello +# Portions created by Tiago Mello are Copyright (C) 2010 +# Tiago Mello. All Rights Reserved. +# +# Contributor(s): Tiago Mello + +package Bugzilla::BugUrl::Launchpad; +use strict; +use base qw(Bugzilla::BugUrl); + +use Bugzilla::Error; + +############################### +#### Methods #### +############################### + +sub should_handle { + my ($class, $uri) = @_; + return ($uri->authority =~ /launchpad.net$/) ? 1 : 0; +} + +sub _check_value { + my ($class, $uri) = @_; + + $uri = $class->SUPER::_check_value($uri); + + my $value = $uri->as_string; + # Launchpad bug URLs can look like various things: + # https://bugs.launchpad.net/ubuntu/+bug/1234 + # https://launchpad.net/bugs/1234 + # All variations end with either "/bugs/1234" or "/+bug/1234" + if ($uri->path =~ m|bugs?/(\d+)$|) { + # This is the shortest standard URL form for Launchpad bugs, + # and so we reduce all URLs to this. + $value = "https://launchpad.net/bugs/$1"; + } + else { + ThrowUserError('bug_url_invalid', { url => $value, reason => 'id' }); + } + + return new URI($value); +} + +1; diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 47c8873fa..9cbd66f42 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -645,6 +645,9 @@ sub update_table_definitions { # 2010-10-09 LpSolit@gmail.com - Bug 451735 _fix_series_indexes(); + $dbh->bz_add_column('bug_see_also', 'id', + {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1}); + ################################################################ # New --TABLE-- changes should go *** A B O V E *** this point # ################################################################ -- cgit v1.2.3-24-g4f1b