Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package MirrorCache for openSUSE:Factory 
checked in at 2022-06-15 00:33:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/MirrorCache (Old)
 and      /work/SRC/openSUSE:Factory/.MirrorCache.new.1548 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "MirrorCache"

Wed Jun 15 00:33:09 2022 rev:15 rq:982588 version:1.034

Changes:
--------
--- /work/SRC/openSUSE:Factory/MirrorCache/MirrorCache.changes  2022-05-26 
18:44:10.645186177 +0200
+++ /work/SRC/openSUSE:Factory/.MirrorCache.new.1548/MirrorCache.changes        
2022-06-15 00:34:11.138692801 +0200
@@ -1,0 +2,8 @@
+Tue Jun 07 09:05:15 UTC 2022 - Andrii Nikitin <andrii.niki...@suse.com>
+
+- Update to version 1.034:
+  * Provide torrent (#278)
+  * Add report for projects on mirrors (#276)
+  * Fix render when metalink is optional (#277)
+
+-------------------------------------------------------------------

Old:
----
  MirrorCache-1.033.obscpio

New:
----
  MirrorCache-1.034.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ MirrorCache.spec ++++++
--- /var/tmp/diff_new_pack.KNLQIW/_old  2022-06-15 00:34:17.486702130 +0200
+++ /var/tmp/diff_new_pack.KNLQIW/_new  2022-06-15 00:34:17.490702136 +0200
@@ -22,7 +22,7 @@
 %define main_requires %{assetpack_requires} perl(Carp) perl(DBD::Pg) >= 3.7.4 
perl(DBI) >= 1.632 perl(DBIx::Class) >= 0.082801 
perl(DBIx::Class::DynamicDefault) perl(DateTime) perl(Encode) perl(Time::Piece) 
perl(Time::Seconds) perl(Time::ParseDate) perl(DateTime::Format::Pg) 
perl(Exporter) perl(File::Basename) perl(LWP::UserAgent) perl(Mojo::Base) 
perl(Mojo::ByteStream) perl(Mojo::IOLoop) perl(Mojo::JSON) perl(Mojo::Pg) 
perl(Mojo::URL) perl(Mojo::Util) perl(Mojolicious::Commands) 
perl(Mojolicious::Plugin) perl(Mojolicious::Plugin::RenderFile) 
perl(Mojolicious::Static) perl(Net::OpenID::Consumer) perl(POSIX) 
perl(Sort::Versions) perl(URI::Escape) perl(XML::Writer) perl(base) 
perl(constant) perl(diagnostics) perl(strict) perl(warnings) shadow 
rubygem(sass) perl(Net::DNS) perl(LWP::Protocol::https) perl(Digest::SHA)
 %define build_requires %{assetpack_requires} rubygem(sass) tidy sysuser-shadow 
sysuser-tools
 Name:           MirrorCache
-Version:        1.033
+Version:        1.034
 Release:        0
 Summary:        WebApp to redirect and manage mirrors
 License:        GPL-2.0-or-later

++++++ MirrorCache-1.033.obscpio -> MirrorCache-1.034.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/assets/assetpack.def 
new/MirrorCache-1.034/assets/assetpack.def
--- old/MirrorCache-1.033/assets/assetpack.def  2022-05-18 14:28:29.000000000 
+0200
+++ new/MirrorCache-1.034/assets/assetpack.def  2022-06-07 10:53:05.000000000 
+0200
@@ -115,6 +115,7 @@
 < http://timeago.yarp.com/jquery.timeago.js
 < javascripts/mirrorcache.js
 < javascripts/mirrorlist.js
+< javascripts/reporttable.js
 < javascripts/admintable.js
 < javascripts/admin_user.js
 < javascripts/audit_log.js
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/assets/javascripts/reporttable.js 
new/MirrorCache-1.034/assets/javascripts/reporttable.js
--- old/MirrorCache-1.033/assets/javascripts/reporttable.js     1970-01-01 
01:00:00.000000000 +0100
+++ new/MirrorCache-1.034/assets/javascripts/reporttable.js     2022-06-07 
10:53:05.000000000 +0200
@@ -0,0 +1,33 @@
+
+function setupReportTable() {
+    // read columns from empty HTML table rendered by the server
+    var columns = [];
+    var thElements = $('.reporttable thead th').each(function() {
+        var th = $(this);
+
+        // add column
+        var columnName;
+        columnName = th.text().trim().replace(/ 
/g,"").toLowerCase().replace(/\./g,"");
+        if (columnName.match(/^\d/)) {
+            columnName = 'c' + columnName;
+        }
+        columns.push({ data: columnName, defaultContent: "" });
+    });
+
+    var url = $("#reporttable_api_url").val();
+    var table = $('.reporttable');
+    var dataTable = table.DataTable({
+        order: [
+            [0, 'asc']
+        ],
+        ajax: {
+            url: url,
+            dataSrc: 'report'
+        },
+        columns: columns,
+        search: {
+            regex: true,
+        },
+    });
+    dataTable.rowData = [];
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/lib/MirrorCache/Datamodule.pm 
new/MirrorCache-1.034/lib/MirrorCache/Datamodule.pm
--- old/MirrorCache-1.033/lib/MirrorCache/Datamodule.pm 2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/Datamodule.pm 2022-06-07 
10:53:05.000000000 +0200
@@ -38,6 +38,7 @@
 has [ '_is_secure', '_is_ipv4', '_ipvstrict', '_is_head' ];
 has 'mirrorlist';
 has 'zsync';
+has [ 'torrent', 'magnet', 'btih' ];
 has 'json';
 has [ 'folder_id', 'file_id', 'file_age', 'folder_sync_last', 
'folder_scan_last' ]; # shortcut to requested folder and file, if known
 
@@ -105,7 +106,7 @@
 }
 
 sub extra($self) {
-    return ($self->metalink || $self->mirrorlist || $self->zsync);
+    return ($self->metalink || $self->mirrorlist || $self->zsync || 
$self->magnet || $self->torrent || $self->btih );
 }
 
 sub region($self) {
@@ -258,10 +259,8 @@
 
 sub redirect($self, $url) {
     my $xtra = '';
-    if ($self->_original_path =~ m/.*\.metalink$/) {
-        $xtra = ".metalink";
-    } elsif ($self->_original_path =~ m/.*\.mirrorlist$/) {
-        $xtra = ".mirrorlist";
+    if ($self->_original_path =~ 
m/(\.metalink|\.mirrorlist|\.torrent|\.magnet|\.btih)$/) {
+        $xtra = $1;
     }
 
     return $self->c->redirect_to($url . $xtra . $self->query1);
@@ -350,6 +349,9 @@
         $self->_query1('?' . $query_string);
         $self->mirrorlist(1) if defined $query->param('mirrorlist');
         $self->zsync(1)      if defined $query->param('zsync');
+        $self->torrent(1)    if defined $query->param('torrent');
+        $self->magnet(1)     if defined $query->param('magnet');
+        $self->btih(1)       if defined $query->param('btih');
         $self->json(1)       if defined $query->param('json') || defined 
$query->param('JSON');
         $pedantic = $query->param('PEDANTIC');
     } else {
@@ -395,6 +397,24 @@
             $path = substr($path, 0, $pos);
         }
     }
+    if (!$trailing_slash && ((my $pos = length($path) - length('.torrent')) > 
1)) {
+        if ('.torrent' eq substr($path, $pos)) {
+            $self->torrent(1);
+            $path = substr($path, 0, $pos);
+        }
+    }
+    if (!$trailing_slash && ((my $pos = length($path) - length('.magnet')) > 
1)) {
+        if ('.magnet' eq substr($path, $pos)) {
+            $self->magnet(1);
+            $path = substr($path, 0, $pos);
+        }
+    }
+    if (!$trailing_slash && ((my $pos = length($path) - length('.btih')) > 1)) 
{
+        if ('.btih' eq substr($path, $pos)) {
+            $self->btih(1);
+            $path = substr($path, 0, $pos);
+        }
+    }
     $pedantic = $ENV{'MIRRORCACHE_PEDANTIC'} unless defined $pedantic;
     if (!defined $pedantic) {
         if ( $path =~ m/.*\/([^\/]*-Current[^\/]*)$/ ) {
@@ -407,6 +427,7 @@
 
     $self->_pedantic($pedantic) if defined $pedantic;
 
+    $self->agent; # parse headers
     $self->must_render_from_root(1)
         if !$self->mirrorlist
         && ( !$self->metalink || $self->metalink_accept )
@@ -419,7 +440,6 @@
     $self->_mime($mime);
     $self->_path($path);
     $self->_trailing_slash($trailing_slash);
-    $self->agent; # parse headers
 }
 
 sub root_is_hit($self) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/Schema/ResultSet/Server.pm 
new/MirrorCache-1.034/lib/MirrorCache/Schema/ResultSet/Server.pm
--- old/MirrorCache-1.033/lib/MirrorCache/Schema/ResultSet/Server.pm    
2022-05-18 14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/Schema/ResultSet/Server.pm    
2022-06-07 10:53:05.000000000 +0200
@@ -247,4 +247,49 @@
     $prep->execute($state, $extra, $server_id, $project_id);
 }
 
+sub report_mirrors {
+    my ($self, $project, $region) = @_;
+    my $rsource = $self->result_source;
+    my $schema  = $rsource->schema;
+    my $dbh     = $schema->storage->dbh;
+
+    my $where1  = '';
+    my $where2  = '';
+    $where1 = "WHERE REPLACE(prj.name,' ','') = ?" if $project;
+    $where2 = "WHERE s.region = ?"  if $region;
+
+    my $sql = <<"END_SQL";
+select s.region, s.country, x.name project, s.id, min(case when s1 = 0 then 1 
else 0 end) as curr, round((sum(s2)*1.0)/(sum(s1)+sum(s2))*100) as score, 
concat(s.hostname, s.urldir) as url, max(example) victim
+from (
+select prj.name, fds.server_id,
+    sum(case when fds.folder_diff_id != fds2.folder_diff_id then 1 else 0 end) 
s1,
+    sum(case when fds.folder_diff_id = fds2.folder_diff_id then 1 else 0 end) 
s2,
+    max(case when fds.folder_diff_id != fds2.folder_diff_id then f.path else 
'' end) example
+from project prj
+join folder f on f.path like concat(prj.path,'%')
+join folder_diff fd on fd.folder_id = f.id
+join folder_diff fd2 on fd2.folder_id = fd.folder_id
+join folder_diff_server fds on fd.id = fds.folder_diff_id
+join folder_diff_server fds2 on fd2.id = fds2.folder_diff_id and 
fds2.server_id = prj.etalon
+$where1
+group by fds2.server_id, prj.name, fds.server_id ) x
+join server s on x.server_id = s.id
+$where2
+group by s.id, x.name
+order by region, country, score, url;
+END_SQL
+    my $prep = $dbh->prepare($sql);
+    if ($project && $region) {
+        $prep->execute($project, $region);
+    } elsif ($project) {
+        $prep->execute($project);
+    } elsif ($region) {
+        $prep->execute($region);
+    } else {
+        $prep->execute;
+    }
+    my $server_arrayref = $dbh->selectall_arrayref($prep, { Slice => {} });
+    return $server_arrayref;
+}
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/lib/MirrorCache/Task/Report.pm 
new/MirrorCache-1.034/lib/MirrorCache/Task/Report.pm
--- old/MirrorCache-1.033/lib/MirrorCache/Task/Report.pm        1970-01-01 
01:00:00.000000000 +0100
+++ new/MirrorCache-1.034/lib/MirrorCache/Task/Report.pm        2022-06-07 
10:53:05.000000000 +0200
@@ -0,0 +1,78 @@
+# Copyright (C) 2022 SUSE LLC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, see <http://www.gnu.org/licenses/>.
+
+package MirrorCache::Task::Report;
+use Mojo::Base 'Mojolicious::Plugin';
+use Mojo::JSON qw(decode_json encode_json);
+
+sub register {
+    my ($self, $app) = @_;
+    $app->minion->add_task(report => sub { _run($app, @_) });
+}
+
+my $DELAY = int($ENV{MIRRORCACHE_SCHEDULE_REPORT_RETRY_INTERVAL} // 15 * 60);
+
+sub _run {
+    my ($app, $job, $once) = @_;
+    my $minion = $app->minion;
+    return $job->finish('Previous report job is still active')
+      unless my $guard = $minion->guard('report', 15*60);
+
+    my $schema = $app->schema;
+
+    my $mirrors = $schema->resultset('Server')->report_mirrors;
+    # this is just tmp structure we use for aggregation
+    my %report;
+    for my $m (@$mirrors) {
+        $report{$m->{region}}{$m->{country}}{$m->{url}}{$m->{project}} = 
[$m->{score},$m->{victim}];
+    }
+    # json expects array, so we collect array here
+    my @report;
+    for my $region (sort keys %report) {
+        my $by_region = $report{$region};
+        for my $country (sort keys %$by_region) {
+            my $by_country = $by_region->{$country};
+            for my $url (sort keys %$by_country) {
+                my %row = (
+                    region  => $region,
+                    country => $country,
+                    url     => $url,
+                );
+                my $by_project = $by_country->{$url};
+                for my $project (sort keys %$by_project) {
+                    my $p = $by_project->{$project};
+                    my $score = $p->[0];
+                    my $victim = $p->[1];
+                    $project =~ tr/ //ds;
+                    $project =~ tr/\.//ds;
+                    $project = lc($project);
+                    $project = "c$project" if $project =~ /^\d/;
+                    $row{$project . 'score'}  = $score;
+                    $row{$project . 'victim'} = $victim;
+                }
+                push @report, \%row;
+            }
+        }
+    }
+    my $json = encode_json(\@report);
+    my $sql = 'insert into report_body select 1, now(), ?';
+
+    $schema->storage->dbh->prepare($sql)->execute($json);
+
+    return $job->finish if $once;
+    return $job->retry({delay => $DELAY});
+}
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Controller/Report/Mirror.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Controller/Report/Mirror.pm
--- old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Controller/Report/Mirror.pm    
1970-01-01 01:00:00.000000000 +0100
+++ new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Controller/Report/Mirror.pm    
2022-06-07 10:53:05.000000000 +0200
@@ -0,0 +1,30 @@
+# Copyright (C) 2022 SUSE LLC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, see <http://www.gnu.org/licenses/>.
+
+package MirrorCache::WebAPI::Controller::Report::Mirror;
+use Mojo::Base 'Mojolicious::Controller';
+
+sub index {
+    my ($self, $template) = @_;
+    my $projects = $self->mcproject->list;
+
+    $self->stash;
+    $self->render(
+        "report/mirror/index",
+        projects       => $projects
+    );
+}
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Controller/Rest/ReportMirror.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Controller/Rest/ReportMirror.pm
--- 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Controller/Rest/ReportMirror.pm    
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Controller/Rest/ReportMirror.pm    
    2022-06-07 10:53:05.000000000 +0200
@@ -0,0 +1,43 @@
+# Copyright (C) 2022 SUSE LLC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, see <http://www.gnu.org/licenses/>.
+
+package MirrorCache::WebAPI::Controller::Rest::ReportMirror;
+use Mojo::Base 'Mojolicious::Controller';
+
+use Mojo::JSON qw(decode_json encode_json);
+use Data::Dumper;
+
+sub list {
+    my ($self)  = @_;
+
+    my $sql = 'select dt, body from report_body where report_id = 1 order by 
dt desc limit 1';
+
+    eval {
+        my @res = $self->schema->storage->dbh->selectrow_array($sql);
+        my $body = $res[1];
+        my $hash = decode_json($body);
+
+        $self->render(
+            json => { report => $hash, dt => $res[0] }
+        );
+    };
+    my $error = $@;
+    if ($error) {
+         print STDERR "RESPMIRRORREPORT : " . $error . "\n";
+         return $self->render(json => {error => $error}, status => 404);
+    }
+}
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/Backstage.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/Backstage.pm
--- old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/Backstage.pm    
2022-05-18 14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/Backstage.pm    
2022-06-07 10:53:05.000000000 +0200
@@ -32,7 +32,7 @@
 }
 
 my @permanent_jobs =
-  qw(folder_sync_schedule_from_misses folder_sync_schedule 
mirror_scan_schedule_from_misses mirror_scan_schedule_from_path_errors 
mirror_scan_schedule cleanup stat_agg_schedule mirror_check_from_stat);
+  qw(folder_sync_schedule_from_misses folder_sync_schedule 
mirror_scan_schedule_from_misses mirror_scan_schedule_from_path_errors 
mirror_scan_schedule cleanup stat_agg_schedule mirror_check_from_stat report);
 
 sub register_tasks {
     my $self = shift;
@@ -54,6 +54,7 @@
         qw(MirrorCache::Task::FolderSync),
         qw(MirrorCache::Task::FolderTree),
         qw(MirrorCache::Task::Cleanup),
+        qw(MirrorCache::Task::Report),
         qw(MirrorCache::Task::StatAggSchedule),
       );
     if (defined $ENV{MIRRORCACHE_PERMANENT_JOBS}) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/Dir.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/Dir.pm
--- old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/Dir.pm  2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/Dir.pm  2022-06-07 
10:53:05.000000000 +0200
@@ -71,8 +71,9 @@
       || _redirect_geo($dm)
       || _redirect_normalized($dm)
       || _render_stats($dm)
-      || _local_render($dm)
-      || _render_from_db($dm);
+      || _local_render($dm, 0) # check if we should render local
+      || _render_from_db($dm)
+      || _local_render($dm, 1); # check if we should render local when 
metalink cannot be provided
 
     my $tx = $c->render_later->tx;
     my $rendered;
@@ -183,7 +184,7 @@
     my ($path, $trailing_slash, $original_path) = $dm->path;
     return undef if $path eq '/';
     $path = $path . '.metalink' if $dm->metalink && !$dm->metalink_accept;
-    return $dm->c->redirect_to($dm->route . $path . $trailing_slash . 
$dm->query1) unless $original_path eq $path || $dm->mirrorlist || $dm->zsync;
+    return $dm->c->redirect_to($dm->route . $path . $trailing_slash . 
$dm->query1) unless $original_path eq $path || ($dm->extra && !$dm->metalink);
     return undef;
 }
 
@@ -242,8 +243,9 @@
 }
 
 sub _local_render {
-    my $dm = shift;
-    return undef if $dm->extra;
+    my $dm     = shift;
+    my $accept = shift;
+    return undef if $dm->extra && (!$accept || !$dm->metalink_accept);
     my ($path, $trailing_slash) = $dm->path;
 
     return $root->render_file_if_nfs($dm, $path) if $root->is_remote;
@@ -272,13 +274,7 @@
                 $dm->folder_id($parent_folder->id);
             } else {
                 my $another_folder = $rsFolder->find({path => 
$dm->root_subtree . $f->dirname});
-                if (!$another_folder) {
-                    my $res = $c->render(status => 425, text => "The file is 
unknown, retry later");
-                    # log miss here even thoough we haven't rendered anything
-                    $c->stat->redirect_to_root($dm, 0);
-                    return $res;
-                }
-                $dm->folder_id($another_folder->id);
+                return undef unless $another_folder; # nothing found, proceed 
to _guess_what_to_render
             }
             my $file;
             $file = 
$schema->resultset('File')->find_with_hash($parent_folder->id, $f->basename) if 
$parent_folder && !$trailing_slash;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/Project.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/Project.pm
--- old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/Project.pm      
1970-01-01 01:00:00.000000000 +0100
+++ new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/Project.pm      
2022-06-07 10:53:05.000000000 +0200
@@ -0,0 +1,64 @@
+# Copyright (C) 2022 SUSE LLC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+package MirrorCache::WebAPI::Plugin::Project;
+use Mojo::Base 'Mojolicious::Plugin';
+use Data::Dumper;
+
+my $initialized = 0;
+my @projects;
+my %projects_path;
+my %projects_alias;
+
+sub register {
+    my ($self, $app) = @_;
+
+    $app->helper('mcproject.list' => \&_list);
+    return $self;
+}
+
+sub _init_if_needed {
+    return 1 if $initialized;
+    my ($c) = @_;
+    $initialized = 1;
+    eval { #the table may be missing - no big deal (only reports might be 
inaccurate if some other error occurred).
+        @projects = $c->schema->resultset('Project')->all;
+        1;
+    } or $c->log->error(Dumper("Cannot load projects", @_));
+
+
+
+    for my $p (@projects) {
+        my $name = $p->name;
+        my $alias = $name;
+        $alias =~ tr/ //ds; # remove spaces
+        $projects_path{$name} = $p->path;
+        $projects_alias{$name} = $alias;
+    }
+}
+
+sub _list {
+    my ($c) = @_;
+    _init_if_needed($c);
+
+    my @res;
+    for my $p (@projects) {
+        push @res, $p->name;
+    }
+    return \@res;
+}
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm
--- old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm 
2022-05-18 14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm 
2022-06-07 10:53:05.000000000 +0200
@@ -25,6 +25,7 @@
 use DateTime;
 use Mojo::File;
 use Mojo::Date;
+use Mojo::Util;
 use Mojo::IOLoop::Subprocess;
 
 sub register {
@@ -89,17 +90,33 @@
         if (!$folder || !$file) {
             return $c->render(status => 404, text => "File not found");
         }
-        if ($dm->zsync) {
-            my $url = $root->is_remote ? $root->location($dm, $folder->path) : 
$root->redirect($dm, $folder->path);
-            if ($url) {
-                $url = $url . "/" . $basename;
-            } else {
-                ($url = $c->req->url->to_abs->to_string) =~ s/\.zsync$//;
+        my $url;
+        if ($dm->torrent || $dm->zsync || $dm->metalink) {
+            $url = $root->is_remote ? $root->location($dm, $folder->path) : 
$root->redirect($dm, $folder->path);
+            if (!$dm->metalink) {
+                if ($url && ! $dm->metalink) {
+                    $url = $url . "/" . $basename;
+                } else {
+                    ($url = $c->req->url->to_abs->to_string) =~ 
s/\.(torrent|zsync)$//;
+                }
             }
+        }
+
+        if ($dm->zsync) {
             _render_zsync($c, $url, $basename, $file->{mtime}, $file->{size}, 
$file->{sha1}, $file->{zblock_size}, $file->{zlengths}, $file->{zhashes});
             $c->stat->redirect_to_root($dm, 1);
             return 1;
         }
+        if ($dm->btih) {
+            _render_btih($c, $basename, $file);
+            $c->stat->redirect_to_root($dm, 1);
+            return 1;
+        }
+        if ($dm->magnet) {
+            _render_magnet($c, $url, $basename, $file);
+            $c->stat->redirect_to_root($dm, 1);
+            return 1;
+        }
 
         my (@mirrors_country, @mirrors_region, @mirrors_rest);
 
@@ -112,7 +129,7 @@
         $mirror = $mirrors_region[0]  if !$mirror && @mirrors_region;
         $mirror = $mirrors_rest[0]    if !$mirror && @mirrors_rest;
 
-        if ($dm->metalink || $dm->mirrorlist) {
+        if ($dm->extra) {
             if ($mirror) {
                 $c->stat->redirect_to_mirror($mirror->{mirror_id}, $dm);
             } else {
@@ -120,29 +137,30 @@
             }
         }
 
-        if ($dm->metalink && !($dm->metalink_accept && 'media.1/media' eq 
substr($filepath,length($filepath)-length('media.1/media')))) {
-            my $url = $c->req->url->to_abs;
+        return _render_torrent($dm, $file, \@mirrors_country, 
\@mirrors_region, \@mirrors_rest, $url) if $dm->torrent;
 
+        if ($dm->metalink && !($dm->metalink_accept && 'media.1/media' eq 
substr($filepath,length($filepath)-length('media.1/media')))) {
             my $origin;
             if (my $publisher_url = $ENV{MIRRORCACHE_METALINK_PUBLISHER_URL}) {
                 $publisher_url =~ s/^https?:\/\///;
                 $origin = $dm->scheme . '://' . $publisher_url;
             } else {
-                $origin = $dm->scheme . '://' . $url->host;
-                $origin = $origin . ":" . $url->port if $url->port && 
$url->port != "80";
+                my $originurl = $c->req->url->to_abs; 
+                $origin = $dm->scheme . '://' . $originurl->host;
+                $origin = $origin . ":" . $originurl->port if $originurl->port 
&& $originurl->port != "80";
                 $origin = $origin . $dm->route;
             }
             $origin = $origin . $filepath;
             my $xml    = _build_metalink(
                 $dm, $folder->path, $file, $country, $region, 
\@mirrors_country, \@mirrors_region,
-                \@mirrors_rest, $origin, 'MirrorCache', $root->is_remote ? 
$root->location($dm) : $root->redirect($dm, $folder->path) );
+                \@mirrors_rest, $origin, 'MirrorCache', $url);
             $c->res->headers->content_disposition('attachment; filename="' 
.$basename. '.metalink"');
             $c->render(data => $xml, format => 'metalink');
             return 1;
         }
 
         if ($dm->mirrorlist) {
-            my $url    = $c->req->url->to_abs;
+            $url = $c->req->url->to_abs;
             my @mirrordata;
             if ($country and !$dm->avoid_countries || !(grep { $country eq $_ 
} $dm->avoid_countries)) {
                 for my $m (@mirrors_country) {
@@ -560,4 +578,106 @@
     return 1;
 }
 
+sub _render_btih() {
+    my ($c, $filename, $file) = @_;
+
+    unless($file->{md5}) {
+        $c->render(status => 404, text => "File not found");
+        return 1;
+    }
+
+    $c->render(text => "$filename " . _calc_btih($filename, $file));
+    return 1;
+}
+
+sub _render_magnet() {
+    my ($c, $url, $filename, $file) = @_;
+
+    unless($file->{piece_size}) {
+        $c->render(status => 404, text => "File not found");
+        return 1;
+    }
+
+    my $btih  = _calc_btih($filename, $file);
+    my $md5   = $file->{md5};
+    my $size  = $file->{size};
+    $filename = Mojo::Util::url_escape($filename);
+    $url      = Mojo::Util::url_escape($url);
+
+    $c->render(text => 
"magnet:?xt=urn:btih:$btih&amp;xt=urn:md5:$md5&amp;xl=$size&amp;dn=$filename&amp;as=$url");
+    return 1;
+}
+
+sub _render_torrent() {
+    my ($dm, $file, $mirrors_country, $mirrors_region, $mirrors_rest, $url) = 
@_;
+
+    my $c = $dm->c;
+
+    unless($file->{piece_size}) {
+        $c->render(status => 404, text => "File not found");
+        return 1;
+    }
+
+    my $tracker     = $ENV{MIRRORCACHE_TRACKER} // 
'http://tracker.opensuse.org:6969/announce';
+    my $trackerlen  = length($tracker);
+    my $filename    = $file->{name};
+    my $filenamelen = length($filename);
+    my $size        = $file->{size};
+    my $mtime       = $file->{mtime};
+    my $md5         = $file->{md5};
+    my $piece_size  = $file->{piece_size};
+    my $sha1        = pack 'H*', $file->{sha1};
+    my $sha256      = pack 'H*', $file->{sha256};
+    my $pieces      = pack 'H*', $file->{pieces};
+
+    my $header = "d8:announce$trackerlen:$tracker" .
+                 "13:announce-listll$trackerlen:${tracker}ee" .
+                 "7:comment$filenamelen:$filename" .
+                 "10:created by11:MirrorCache13:creation datei${mtime}e" .
+                 "4:infod6:lengthi${size}e" .
+                 "6:md5sum32:$md5" .
+                 "4:name$filenamelen:$filename" .
+                 "12:piece lengthi${piece_size}e" .
+                 "6:pieces" . length($pieces) . ":";
+
+    my $footer = "4:sha120:$sha1" .
+                 "6:sha25632:${sha256}e" .
+                 "7:sourcesl";
+    if (scalar(@$mirrors_country) > 0 || scalar(@$mirrors_region) > 0 || 
scalar(@$mirrors_rest) > 0) {
+        for my $m (@$mirrors_country, @$mirrors_region, @$mirrors_rest) {
+            $footer = $footer . length($m->{url}) . ":" . $m->{url};
+        }
+    } else {
+        $footer = $footer . length($url) . ":" . $url;
+    }
+    $footer = $footer . 'ee';
+
+    $c->res->headers->content_length(length($header) + length($pieces) + 
length($footer));
+    $c->write($header => sub () {
+            $c->write($pieces => sub () {
+                $c->write($footer => sub () {$c->finish});
+            })
+        });
+
+    return 1;
+}
+
+sub _calc_btih() {
+    my ($filename, $file) = @_;
+
+    my $sha1 = Digest::SHA->new(1);
+    $sha1->
+        add('d')->
+        add('6:lengthi:' . $file->{size})->
+        add('6:md5sum32:' . $file->{md5})->
+        add('4:name' . length($filename) . ":$filename")->
+        add('12:piece lengthi:' . $file->{piece_size})->
+        add('6:pieces:' . length($file->{pieces}))->add($file->{pieces})->
+        add('4:sha120:' . $file->{sha1})->
+        add('6:sha25632:' . $file->{sha256})->
+        add('e');
+
+    return $sha1->hexdigest;
+}
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm
--- old/MirrorCache-1.033/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm    
2022-05-18 14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm    
2022-06-07 10:53:05.000000000 +0200
@@ -79,7 +79,9 @@
     if ($redirect) {
         $res = !!$c->redirect_to($redirect . $root_subtree . $filepath);
     } else {
-        $res = !!$c->render_file(filepath => $self->rootpath($filepath) . 
$root_subtree . $filepath, content_type => $dm->mime);
+        my $rootpath = $self->rootpath($filepath);
+        return !!$c->render(status => 404, text => "File $filepath not found") 
unless $rootpath;
+        $res = !!$c->render_file(filepath => $rootpath . $root_subtree . 
$filepath, content_type => $dm->mime);
     }
     $c->stat->redirect_to_root($dm, $not_miss);
     return $res;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/lib/MirrorCache/WebAPI.pm 
new/MirrorCache-1.034/lib/MirrorCache/WebAPI.pm
--- old/MirrorCache-1.033/lib/MirrorCache/WebAPI.pm     2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/WebAPI.pm     2022-06-07 
10:53:05.000000000 +0200
@@ -116,6 +116,7 @@
 
     $self->plugin('Helpers', root => $root, route => '/download');
     $self->plugin('Subsidiary');
+    $self->plugin('Project');
     if ($root) {
         # check prefix
         if ('rsync://' eq substr($root, 0, 8)) {
@@ -183,6 +184,7 @@
     
$rest_usr_r->put('/myserver/location/:id')->name('rest_put_myserver_location')->to('myserver_location#update_location');
 
     $rest_r->get('/folder')->name('rest_folder')->to('table#list', table => 
'Folder');
+    
$rest_r->get('/repmirror')->name('rest_repmirror')->to('report_mirror#list');
 
     
$rest_r->get('/folder_jobs/:id')->name('rest_folder_jobs')->to('folder_jobs#list');
     $rest_r->get('/myip')->name('rest_myip')->to('my_ip#show') if 
$self->_geodb;
@@ -190,6 +192,9 @@
     $rest_r->get('/stat')->name('rest_stat')->to('stat#list');
     $rest_r->get('/mystat')->name('rest_mystat')->to('stat#mylist');
 
+    my $report_r = $r->any('/report')->to(namespace => 
'MirrorCache::WebAPI::Controller::Report');
+    $report_r->get('/mirror')->name('report_mirror')->to('mirror#index');
+
     my $app_r = $r->any('/app')->to(namespace => 
'MirrorCache::WebAPI::Controller::App');
 
     $app_r->get('/server')->name('server')->to('server#index');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/resources/migrations/Pg.sql 
new/MirrorCache-1.034/lib/MirrorCache/resources/migrations/Pg.sql
--- old/MirrorCache-1.033/lib/MirrorCache/resources/migrations/Pg.sql   
2022-05-18 14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/resources/migrations/Pg.sql   
2022-06-07 10:53:05.000000000 +0200
@@ -280,3 +280,17 @@
     username varchar(64) not null,
     primary key(server_id,username)
 );
+-- 24 up
+create table report (
+    id serial NOT NULL PRIMARY KEY,
+    title       varchar(64),
+    description varchar(256),
+    interval_seconds int DEFAULT 3600
+);
+insert into report select 1, 'Mirrors', NULL, 15*60;
+create table report_body (
+    report_id int references report on delete cascade,
+    dt timestamp,
+    body text
+);
+create index if not exists report_content_dt_inx on report_body(report_id, dt);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/lib/MirrorCache/resources/migrations/mysql.sql 
new/MirrorCache-1.034/lib/MirrorCache/resources/migrations/mysql.sql
--- old/MirrorCache-1.033/lib/MirrorCache/resources/migrations/mysql.sql        
2022-05-18 14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/lib/MirrorCache/resources/migrations/mysql.sql        
2022-06-07 10:53:05.000000000 +0200
@@ -276,3 +276,18 @@
     primary key(server_id,username),
     constraint `fk_server_admin` FOREIGN KEY(server_id) references server(id) 
on delete cascade
 );
+-- 24 up
+create table report (
+    id int AUTO_INCREMENT NOT NULL PRIMARY KEY,
+    title       varchar(64),
+    description varchar(256),
+    interval_seconds int DEFAULT 3600
+);
+insert into report select 1, 'Mirrors', NULL, 15*60;
+create table report_body (
+    report_id int,
+    dt timestamp,
+    body text,
+    constraint `fk_report_body_report` FOREIGN KEY(report_id) references 
report(id) on delete cascade
+);
+create index if not exists report_content_dt_inx on report_body(report_id, dt);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/t/environ/02-files-hashes.sh 
new/MirrorCache-1.034/t/environ/02-files-hashes.sh
--- old/MirrorCache-1.033/t/environ/02-files-hashes.sh  2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/t/environ/02-files-hashes.sh  2022-06-07 
10:53:05.000000000 +0200
@@ -57,3 +57,12 @@
 $mc/curl /download/folder1/file1.1.dat.metalink | grep -o '<hash 
type="md5">b2c5860a03d2c4f1f049a3b2409b39a8</hash>'
 $mc/curl /download/folder1/file1.1.dat.metalink | grep -o '<hash 
type="sha-256">63d19a99ef7db94ddbb1e4a5083062226551cd8197312e3aa0aa7c369ac3e458</hash>'
 $mc/curl /download/folder1/file1.1.dat.metalink | grep -o 
'<hash>5179db3d4263c9cb4ecf0edbc653ca460e3678b7</hash>'
+
+$mc/curl -I /download/folder1/file1.1.dat.btih | grep '200 OK'
+$mc/curl /download/folder1/file1.1.dat.btih
+$mc/curl -I /download/folder1/file1.1.dat.magnet | grep '200 OK'
+$mc/curl /download/folder1/file1.1.dat.magnet
+$mc/curl -I /download/folder1/file1.1.dat.torrent | grep '200 OK'
+$mc/curl /download/folder1/file1.1.dat.torrent
+
+echo success
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/t/environ/02-files.sh 
new/MirrorCache-1.034/t/environ/02-files.sh
--- old/MirrorCache-1.033/t/environ/02-files.sh 2022-05-18 14:28:29.000000000 
+0200
+++ new/MirrorCache-1.034/t/environ/02-files.sh 2022-06-07 10:53:05.000000000 
+0200
@@ -22,10 +22,11 @@
 
 for x in $mc $ap7 $ap8; do
     mkdir -p $x/dt/{folder1,folder2,folder3}
-    mkdir -p $x/dt/Folder1
+    mkdir -p $x/dt/Folder1/repodata
     echo $x/dt/{folder1,folder2,folder3}/{file1.1,file2.1}.dat | xargs -n 1 
touch
     echo $x/dt/folder1/file1.dat | xargs -n 1 touch
     echo $x/dt/Folder1/file1.1.DAT | xargs -n 1 touch
+    echo $x/dt/Folder1/repodata/repomd.xml | xargs -n 1 touch
     mkdir -p $x/dt/folder1.11test/
     for f in $unversionedfiles; do
         str=1
@@ -37,6 +38,8 @@
 $ap7/start
 $ap8/start
 
+$mc/curl -I -H "Accept: */*, application/metalink+xml" 
/download/Folder1/repodata/repomd.xml | grep '200 OK'
+
 $mc/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap7/print_address)','','t','us','na'"
 $mc/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap8/print_address)','','t','ca','na'"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/t/environ/14-project.sh 
new/MirrorCache-1.034/t/environ/14-project.sh
--- old/MirrorCache-1.033/t/environ/14-project.sh       2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/t/environ/14-project.sh       2022-06-07 
10:53:05.000000000 +0200
@@ -12,8 +12,10 @@
 for x in $mc $ap7 $ap8 $ap6; do
     mkdir -p $x/dt/{folder1,folder2,folder3}
     mkdir -p $x/dt/project1/{folder1,folder2,folder3}
+    mkdir -p $x/dt/project2/{folder1,folder2,folder3}
     echo $x/dt/{folder1,folder2,folder3}/{file1.1,file2.1}.dat | xargs -n 1 
touch
     echo $x/dt/project1/{folder1,folder2,folder3}/{file1.1,file2.1}.dat | 
xargs -n 1 touch
+    echo $x/dt/project2/{folder1,folder2,folder3}/{file1.1,file2.1}.dat | 
xargs -n 1 touch
 done
 
 $ap6/start
@@ -25,9 +27,10 @@
 
 $mc/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap6/print_address)','','t','us','na'"
 $mc/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap7/print_address)','','t','us','na'"
-$mc/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap8/print_address)','','t','us','na'"
+$mc/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap8/print_address)','','t','de','eu'"
 
-$mc/sql "insert into project(name,path,etalon) select 'proj1','/project1', 1"
+$mc/sql "insert into project(name,path,etalon) select 'proj1','/project1', 3"
+$mc/sql "insert into project(name,path,etalon) select 'proj 2','/project2', 3"
 
 $mc/backstage/job -e folder_sync -a '["/project1/folder1"]'
 $mc/backstage/job -e mirror_scan -a '["/project1/folder1","us"]'
@@ -40,11 +43,20 @@
 
 
 $mc/backstage/job -e folder_sync -a '["/project1/folder2"]'
-$mc/backstage/job -e mirror_scan -a '["/project1/folder2","us"]'
+$mc/backstage/job -e mirror_scan -a '["/project1/folder2"]'
 $mc/backstage/shoot
+
+$mc/backstage/job -e folder_sync -a '["/project2/folder1"]'
+$mc/backstage/job -e mirror_scan -a '["/project2/folder1"]'
+$mc/backstage/shoot
+
+$mc/backstage/job -e report -a '["once"]'
+$mc/backstage/shoot
+
+$mc/curl -s /rest/repmirror  | grep 
'[{"country":"de","proj1score":"100","proj1victim":"","proj2score":"100","proj2victim":"","region":"eu","url":"127.0.0.1:1314"},{"country":"us","proj1score":"100","proj1victim":"","proj2score":"100","proj2victim":"","region":"na","url":"127.0.0.1:1294"},{"country":"us","proj1score":"50","proj1victim":"\/project1\/folder2","proj2score":"100","proj2victim":"","region":"na","url":"127.0.0.1:1304"}]'
+
 $mc/curl -s /rest/project/proj1/mirror_summary
 $mc/curl -s /rest/project/proj1/mirror_summary | grep -E '"current":"?2' | 
grep -E '"outdated":"?1'
 
-$mc/curl -s /rest/project/proj1/mirror_list
 # $mc/curl -s /rest/project/proj1/mirror_list | grep -E 
'{"current":"?1"?,"server_id":"?1"?,"url":"127.0.0.1:1294"},{"current":"?1"?,"server_id":"?3"?,"url":"127.0.0.1:1314"},{"current":"?0"?,"server_id":"?2"?,"url":"127.0.0.1:1304"}'
 $mc/curl -s /rest/project/proj1/mirror_list | grep 
'{"current":1,"server_id":1,"url":"127.0.0.1:1294"},{"current":1,"server_id":3,"url":"127.0.0.1:1314"},{"current":0,"server_id":2,"url":"127.0.0.1:1304"}'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/t/lib/Dockerfile.environ.mariadb 
new/MirrorCache-1.034/t/lib/Dockerfile.environ.mariadb
--- old/MirrorCache-1.033/t/lib/Dockerfile.environ.mariadb      2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/t/lib/Dockerfile.environ.mariadb      2022-06-07 
10:53:05.000000000 +0200
@@ -5,7 +5,6 @@
 
 RUN sed -i 
's,http://download.opensuse.org,http://mirrorcache.opensuse.org/download,g' 
/etc/zypp/repos.d/*repo
 RUN zypper ar -f 
http://mirrorcache.opensuse.org/repositories/openSUSE:infrastructure:MirrorCache/openSUSE_Leap_15.3
 mc
-RUN zypper ar -f 
http://mirrorcache.opensuse.org/repositories/home:/andriinikitin:/branches:/devel:/languages:/perl:/CPAN-M/15.3
 pm
 RUN zypper ar -f 
http://mirrorcache.opensuse.org/repositories/devel:/languages:/perl/openSUSE_Leap_15.3
 perl
 RUN zypper --gpg-auto-import-keys ref
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/t/lib/Dockerfile.environ.postgresql 
new/MirrorCache-1.034/t/lib/Dockerfile.environ.postgresql
--- old/MirrorCache-1.033/t/lib/Dockerfile.environ.postgresql   2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/t/lib/Dockerfile.environ.postgresql   2022-06-07 
10:53:05.000000000 +0200
@@ -5,7 +5,6 @@
 
 RUN sed -i 
's,http://download.opensuse.org,http://mirrorcache.opensuse.org/download,g' 
/etc/zypp/repos.d/*repo
 RUN zypper ar -f 
http://mirrorcache.opensuse.org/repositories/openSUSE:infrastructure:MirrorCache/openSUSE_Leap_15.3
 mc
-RUN zypper ar -f 
http://mirrorcache.opensuse.org/repositories/home:/andriinikitin:/branches:/devel:/languages:/perl:/CPAN-M/15.3
 pm
 RUN zypper --gpg-auto-import-keys ref
 
 # install MirrorCache here to fetch all dependencies
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.033/t/lib/Dockerfile.systemd.mariadb 
new/MirrorCache-1.034/t/lib/Dockerfile.systemd.mariadb
--- old/MirrorCache-1.033/t/lib/Dockerfile.systemd.mariadb      2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/t/lib/Dockerfile.systemd.mariadb      2022-06-07 
10:53:05.000000000 +0200
@@ -5,7 +5,6 @@
 
 RUN sed -i 
's,http://download.opensuse.org,https://mirrorcache.opensuse.org/download,g' 
/etc/zypp/repos.d/*repo
 RUN zypper ar -f 
https://mirrorcache.opensuse.org/repositories/openSUSE:infrastructure:MirrorCache/openSUSE_Leap_15.3
 mc
-RUN zypper ar -f 
https://download.opensuse.org/repositories/home:/andriinikitin:/branches:/devel:/languages:/perl:/CPAN-M/15.3
 pm
 RUN zypper ar -f 
https://download.opensuse.org/repositories/devel:/languages:/perl/openSUSE_Leap_15.3
 perl
 RUN zypper --gpg-auto-import-keys ref
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/t/lib/Dockerfile.systemd.postgresql 
new/MirrorCache-1.034/t/lib/Dockerfile.systemd.postgresql
--- old/MirrorCache-1.033/t/lib/Dockerfile.systemd.postgresql   2022-05-18 
14:28:29.000000000 +0200
+++ new/MirrorCache-1.034/t/lib/Dockerfile.systemd.postgresql   2022-06-07 
10:53:05.000000000 +0200
@@ -5,7 +5,6 @@
 
 RUN sed -i 
's,http://download.opensuse.org,http://mirrorcache.opensuse.org/download,g' 
/etc/zypp/repos.d/*repo
 RUN zypper ar -f 
http://mirrorcache.opensuse.org/repositories/openSUSE:infrastructure:MirrorCache/openSUSE_Leap_15.3
 mc
-RUN zypper ar -f 
http://mirrorcache.opensuse.org/repositories/home:/andriinikitin:/branches:/devel:/languages:/perl:/CPAN-M/15.3
 pm
 RUN zypper --gpg-auto-import-keys ref
 
 # install MirrorCache here to fetch all dependencies
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.033/templates/report/mirror/index.html.ep 
new/MirrorCache-1.034/templates/report/mirror/index.html.ep
--- old/MirrorCache-1.033/templates/report/mirror/index.html.ep 1970-01-01 
01:00:00.000000000 +0100
+++ new/MirrorCache-1.034/templates/report/mirror/index.html.ep 2022-06-07 
10:53:05.000000000 +0200
@@ -0,0 +1,31 @@
+% layout 'bootstrap';
+% title 'Mirror Report';
+
+% content_for 'ready_function' => begin
+    setupReportTable();
+% end
+
+<div class="row">
+    <div class="col-sm-12">
+        <h2><%= title %></h2>
+
+        %= include 'layouts/info'
+
+        <table id="servers" class="reporttable table table-striped">
+            <thead>
+                <tr>
+                    <th class="col_value">Region</th>
+                    <th class="col_value">Country</th>
+                    <th class="col_value">Url</th>
+                    % for my $project (@$projects) {
+                    <th class="col_value"><%= $project  %> score</th>
+                    <th class="col_value"><%= $project  %> victim</th>
+                    % }
+                </tr>
+            </thead>
+            <tbody>
+            </tbody>
+        </table>
+        <input type="hidden" id="reporttable_api_url" value="/rest/repmirror"/>
+    </div>
+</div>

++++++ MirrorCache.obsinfo ++++++
--- /var/tmp/diff_new_pack.KNLQIW/_old  2022-06-15 00:34:17.790702577 +0200
+++ /var/tmp/diff_new_pack.KNLQIW/_new  2022-06-15 00:34:17.794702582 +0200
@@ -1,5 +1,5 @@
 name: MirrorCache
-version: 1.033
-mtime: 1652876909
-commit: f58f3923539b52c99a595c5654134826a15191c9
+version: 1.034
+mtime: 1654591985
+commit: 2650bc3c1b58c91f67aabc3e58ca518015eca3cc
 

++++++ cache.tar.xz ++++++

Reply via email to