summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Update.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Update.pm')
-rw-r--r--Bugzilla/Update.pm274
1 files changed, 142 insertions, 132 deletions
diff --git a/Bugzilla/Update.pm b/Bugzilla/Update.pm
index 72a7108a8..9f9288162 100644
--- a/Bugzilla/Update.pm
+++ b/Bugzilla/Update.pm
@@ -13,149 +13,159 @@ use warnings;
use Bugzilla::Constants;
-use constant TIME_INTERVAL => 86400; # Default is one day, in seconds.
-use constant TIMEOUT => 5; # Number of seconds before timeout.
+use constant TIME_INTERVAL => 86400; # Default is one day, in seconds.
+use constant TIMEOUT => 5; # Number of seconds before timeout.
# Look for new releases and notify logged in administrators about them.
sub get_notifications {
- return if !Bugzilla->feature('updates');
- return if (Bugzilla->params->{'upgrade_notification'} eq 'disabled');
-
- my $local_file = bz_locations()->{'datadir'} . '/' . LOCAL_FILE;
- # Update the local XML file if this one doesn't exist or if
- # the last modification time (stat[9]) is older than TIME_INTERVAL.
- if (!-e $local_file || (time() - (stat($local_file))[9] > TIME_INTERVAL)) {
- unlink $local_file; # Make sure the old copy is away.
- return { 'error' => 'no_update' } if (-e $local_file);
-
- my $error = _synchronize_data();
- # If an error is returned, leave now.
- return $error if $error;
+ return if !Bugzilla->feature('updates');
+ return if (Bugzilla->params->{'upgrade_notification'} eq 'disabled');
+
+ my $local_file = bz_locations()->{'datadir'} . '/' . LOCAL_FILE;
+
+ # Update the local XML file if this one doesn't exist or if
+ # the last modification time (stat[9]) is older than TIME_INTERVAL.
+ if (!-e $local_file || (time() - (stat($local_file))[9] > TIME_INTERVAL)) {
+ unlink $local_file; # Make sure the old copy is away.
+ return {'error' => 'no_update'} if (-e $local_file);
+
+ my $error = _synchronize_data();
+
+ # If an error is returned, leave now.
+ return $error if $error;
+ }
+
+ # If we cannot access the local XML file, ignore it.
+ return {'error' => 'no_access'} unless (-r $local_file);
+
+ my $twig = XML::Twig->new();
+ $twig->safe_parsefile($local_file);
+
+ # If the XML file is invalid, return.
+ return {'error' => 'corrupted'} if $@;
+ my $root = $twig->root;
+
+ my @releases;
+ foreach my $branch ($root->children('branch')) {
+ my $release = {
+ 'branch_ver' => $branch->{'att'}->{'id'},
+ 'latest_ver' => $branch->{'att'}->{'vid'},
+ 'status' => $branch->{'att'}->{'status'},
+ 'url' => $branch->{'att'}->{'url'},
+ 'date' => $branch->{'att'}->{'date'}
+ };
+ push(@releases, $release);
+ }
+
+ # On which branch is the current installation running?
+ my @current_version
+ = (BUGZILLA_VERSION =~ m/^(\d+)\.(\d+)(?:(rc|\.)(\d+))?\+?$/);
+
+ my @release;
+ if (Bugzilla->params->{'upgrade_notification'} eq 'development_snapshot') {
+ @release = grep { $_->{'status'} eq 'development' } @releases;
+
+ # If there is no development snapshot available, then we are in the
+ # process of releasing a release candidate. That's the release we want.
+ unless (scalar(@release)) {
+ @release = grep { $_->{'status'} eq 'release-candidate' } @releases;
}
-
- # If we cannot access the local XML file, ignore it.
- return { 'error' => 'no_access' } unless (-r $local_file);
-
- my $twig = XML::Twig->new();
- $twig->safe_parsefile($local_file);
- # If the XML file is invalid, return.
- return { 'error' => 'corrupted' } if $@;
- my $root = $twig->root;
-
- my @releases;
- foreach my $branch ($root->children('branch')) {
- my $release = {
- 'branch_ver' => $branch->{'att'}->{'id'},
- 'latest_ver' => $branch->{'att'}->{'vid'},
- 'status' => $branch->{'att'}->{'status'},
- 'url' => $branch->{'att'}->{'url'},
- 'date' => $branch->{'att'}->{'date'}
- };
- push(@releases, $release);
- }
-
- # On which branch is the current installation running?
- my @current_version =
- (BUGZILLA_VERSION =~ m/^(\d+)\.(\d+)(?:(rc|\.)(\d+))?\+?$/);
-
- my @release;
- if (Bugzilla->params->{'upgrade_notification'} eq 'development_snapshot') {
- @release = grep {$_->{'status'} eq 'development'} @releases;
- # If there is no development snapshot available, then we are in the
- # process of releasing a release candidate. That's the release we want.
- unless (scalar(@release)) {
- @release = grep {$_->{'status'} eq 'release-candidate'} @releases;
- }
- }
- elsif (Bugzilla->params->{'upgrade_notification'} eq 'latest_stable_release') {
- @release = grep {$_->{'status'} eq 'stable'} @releases;
- }
- elsif (Bugzilla->params->{'upgrade_notification'} eq 'stable_branch_release') {
- # We want the latest stable version for the current branch.
- # If we are running a development snapshot, we won't match anything.
- my $branch_version = $current_version[0] . '.' . $current_version[1];
-
- # We do a string comparison instead of a numerical one, because
- # e.g. 2.2 == 2.20, but 2.2 ne 2.20 (and 2.2 is indeed much older).
- @release = grep {$_->{'branch_ver'} eq $branch_version} @releases;
-
- # If the branch is now closed, we should strongly suggest
- # to upgrade to the latest stable release available.
- if (scalar(@release) && $release[0]->{'status'} eq 'closed') {
- @release = grep {$_->{'status'} eq 'stable'} @releases;
- return {'data' => $release[0], 'deprecated' => $branch_version};
- }
+ }
+ elsif (Bugzilla->params->{'upgrade_notification'} eq 'latest_stable_release') {
+ @release = grep { $_->{'status'} eq 'stable' } @releases;
+ }
+ elsif (Bugzilla->params->{'upgrade_notification'} eq 'stable_branch_release') {
+
+ # We want the latest stable version for the current branch.
+ # If we are running a development snapshot, we won't match anything.
+ my $branch_version = $current_version[0] . '.' . $current_version[1];
+
+ # We do a string comparison instead of a numerical one, because
+ # e.g. 2.2 == 2.20, but 2.2 ne 2.20 (and 2.2 is indeed much older).
+ @release = grep { $_->{'branch_ver'} eq $branch_version } @releases;
+
+ # If the branch is now closed, we should strongly suggest
+ # to upgrade to the latest stable release available.
+ if (scalar(@release) && $release[0]->{'status'} eq 'closed') {
+ @release = grep { $_->{'status'} eq 'stable' } @releases;
+ return {'data' => $release[0], 'deprecated' => $branch_version};
}
- else {
- # Unknown parameter.
- return {'error' => 'unknown_parameter'};
- }
-
- # Return if no new release is available.
- return unless scalar(@release);
-
- # Only notify the administrator if the latest version available
- # is newer than the current one.
- my @new_version =
- ($release[0]->{'latest_ver'} =~ m/^(\d+)\.(\d+)(?:(rc|\.)(\d+))?\+?$/);
-
- # We convert release candidates 'rc' to integers (rc ? 0 : 1) in order
- # to compare versions easily.
- $current_version[2] = ($current_version[2] && $current_version[2] eq 'rc') ? 0 : 1;
- $new_version[2] = ($new_version[2] && $new_version[2] eq 'rc') ? 0 : 1;
-
- my $is_newer = _compare_versions(\@current_version, \@new_version);
- return ($is_newer == 1) ? {'data' => $release[0]} : undef;
+ }
+ else {
+ # Unknown parameter.
+ return {'error' => 'unknown_parameter'};
+ }
+
+ # Return if no new release is available.
+ return unless scalar(@release);
+
+ # Only notify the administrator if the latest version available
+ # is newer than the current one.
+ my @new_version
+ = ($release[0]->{'latest_ver'} =~ m/^(\d+)\.(\d+)(?:(rc|\.)(\d+))?\+?$/);
+
+ # We convert release candidates 'rc' to integers (rc ? 0 : 1) in order
+ # to compare versions easily.
+ $current_version[2]
+ = ($current_version[2] && $current_version[2] eq 'rc') ? 0 : 1;
+ $new_version[2] = ($new_version[2] && $new_version[2] eq 'rc') ? 0 : 1;
+
+ my $is_newer = _compare_versions(\@current_version, \@new_version);
+ return ($is_newer == 1) ? {'data' => $release[0]} : undef;
}
sub _synchronize_data {
- my $local_file = bz_locations()->{'datadir'} . '/' . LOCAL_FILE;
-
- my $ua = LWP::UserAgent->new();
- $ua->timeout(TIMEOUT);
- $ua->protocols_allowed(['http', 'https']);
- # If the URL of the proxy is given, use it, else get this information
- # from the environment variable.
- my $proxy_url = Bugzilla->params->{'proxy_url'};
- if ($proxy_url) {
- $ua->proxy(['http', 'https'], $proxy_url);
- }
- else {
- $ua->env_proxy;
- }
- my $response = eval { $ua->mirror(REMOTE_FILE, $local_file) };
-
- # $ua->mirror() forces the modification time of the local XML file
- # to match the modification time of the remote one.
- # So we have to update it manually to reflect that a newer version
- # of the file has effectively been requested. This will avoid
- # any new download for the next TIME_INTERVAL.
- if (-e $local_file) {
- # Try to alter its last modification time.
- my $can_alter = utime(undef, undef, $local_file);
- # This error should never happen.
- $can_alter || return { 'error' => 'no_update' };
- }
- elsif ($response && $response->is_error) {
- # We have been unable to download the file.
- return { 'error' => 'cannot_download', 'reason' => $response->status_line };
- }
- else {
- return { 'error' => 'no_write', 'reason' => $@ };
- }
-
- # Everything went well.
- return 0;
+ my $local_file = bz_locations()->{'datadir'} . '/' . LOCAL_FILE;
+
+ my $ua = LWP::UserAgent->new();
+ $ua->timeout(TIMEOUT);
+ $ua->protocols_allowed(['http', 'https']);
+
+ # If the URL of the proxy is given, use it, else get this information
+ # from the environment variable.
+ my $proxy_url = Bugzilla->params->{'proxy_url'};
+ if ($proxy_url) {
+ $ua->proxy(['http', 'https'], $proxy_url);
+ }
+ else {
+ $ua->env_proxy;
+ }
+ my $response = eval { $ua->mirror(REMOTE_FILE, $local_file) };
+
+ # $ua->mirror() forces the modification time of the local XML file
+ # to match the modification time of the remote one.
+ # So we have to update it manually to reflect that a newer version
+ # of the file has effectively been requested. This will avoid
+ # any new download for the next TIME_INTERVAL.
+ if (-e $local_file) {
+
+ # Try to alter its last modification time.
+ my $can_alter = utime(undef, undef, $local_file);
+
+ # This error should never happen.
+ $can_alter || return {'error' => 'no_update'};
+ }
+ elsif ($response && $response->is_error) {
+
+ # We have been unable to download the file.
+ return {'error' => 'cannot_download', 'reason' => $response->status_line};
+ }
+ else {
+ return {'error' => 'no_write', 'reason' => $@};
+ }
+
+ # Everything went well.
+ return 0;
}
sub _compare_versions {
- my ($old_ver, $new_ver) = @_;
- while (scalar(@$old_ver) && scalar(@$new_ver)) {
- my $old = shift(@$old_ver) || 0;
- my $new = shift(@$new_ver) || 0;
- return $new <=> $old if ($new <=> $old);
- }
- return scalar(@$new_ver) <=> scalar(@$old_ver);
+ my ($old_ver, $new_ver) = @_;
+ while (scalar(@$old_ver) && scalar(@$new_ver)) {
+ my $old = shift(@$old_ver) || 0;
+ my $new = shift(@$new_ver) || 0;
+ return $new <=> $old if ($new <=> $old);
+ }
+ return scalar(@$new_ver) <=> scalar(@$old_ver);
}