Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package MirrorCache for openSUSE:Factory 
checked in at 2023-02-16 16:57:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/MirrorCache (Old)
 and      /work/SRC/openSUSE:Factory/.MirrorCache.new.22824 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "MirrorCache"

Thu Feb 16 16:57:08 2023 rev:24 rq:1066141 version:1.056

Changes:
--------
--- /work/SRC/openSUSE:Factory/MirrorCache/MirrorCache.changes  2023-01-19 
16:44:28.333852717 +0100
+++ /work/SRC/openSUSE:Factory/.MirrorCache.new.22824/MirrorCache.changes       
2023-02-16 16:57:13.392295114 +0100
@@ -1,0 +2,33 @@
+Thu Feb 09 09:41:42 UTC 2023 - Andrii Nikitin <andrii.niki...@suse.com>
+
+- Update to version 1.056:
+  * Improve symlink handling when remote root references another remote root 
(#353)
+  * ui: add content-disposition inline to render_file (#355)
+  * Don't send users to Bugzilla by @AdamMajer (#357)
+  * Add leap 15.5 to project list (#358)
+  * Add GNOME iso to Current pattern (#356)
+
+-------------------------------------------------------------------
+Thu Feb 02 12:01:48 UTC 2023 - Andrii Nikitin <andrii.niki...@suse.com>
+
+- Update to version 1.055:
+  * Handle redirects with RootRemote (#351)
+  * Add sha512 to hash (#352)
+  * Do not urlencode plus character (#352)
+
+-------------------------------------------------------------------
+Fri Jan 27 13:16:17 UTC 2023 - Andrii Nikitin <andrii.niki...@suse.com>
+
+- Update to version 1.054:
+  * Optimise sql for erasing folder_diff_server (#347)
+  * Fix huge files rendered from REDIRECT_HUGE only for metalink (#348)
+
+-------------------------------------------------------------------
+Thu Jan 26 07:23:04 UTC 2023 - Andrii Nikitin <andrii.niki...@suse.com>
+
+- Update to version 1.053:
+  * Add MIRROR_PROVIDER to share mirror list (#343)
+  * Fix REDIRECT_HUGE with local files (#345)
+  * ui: Dont encode colon character in file names (#346)
+
+-------------------------------------------------------------------

Old:
----
  MirrorCache-1.052.obscpio

New:
----
  MirrorCache-1.056.obscpio

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

Other differences:
------------------
++++++ MirrorCache.spec ++++++
--- /var/tmp/diff_new_pack.6eIJvz/_old  2023-02-16 16:57:14.004297776 +0100
+++ /var/tmp/diff_new_pack.6eIJvz/_new  2023-02-16 16:57:14.008297793 +0100
@@ -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) 
perl(Config::IniFiles)
 %define build_requires %{assetpack_requires} rubygem(sass) tidy sysuser-shadow 
sysuser-tools
 Name:           MirrorCache
-Version:        1.052
+Version:        1.056
 Release:        0
 Summary:        WebApp to redirect and manage mirrors
 License:        GPL-2.0-or-later

++++++ MirrorCache-1.052.obscpio -> MirrorCache-1.056.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/.github/workflows/publish-docs.yml 
new/MirrorCache-1.056/.github/workflows/publish-docs.yml
--- old/MirrorCache-1.052/.github/workflows/publish-docs.yml    2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/.github/workflows/publish-docs.yml    2023-02-09 
09:52:35.000000000 +0100
@@ -3,6 +3,9 @@
   push:
     branches:
       - master
+    paths:
+      - README.md
+      - docs/**
 
 jobs:
   build:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/assets/javascripts/admintable.js 
new/MirrorCache-1.056/assets/javascripts/admintable.js
--- old/MirrorCache-1.052/assets/javascripts/admintable.js      2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/assets/javascripts/admintable.js      2023-02-09 
09:52:35.000000000 +0100
@@ -396,7 +396,7 @@
     });
 
     // setup admin table
-    var url = $("#admintable_api_url").val();
+    var url = $("#admintable_api_url").val() + window.location.search;
     var table = $('.admintable');
     var dataTable = table.DataTable({
         order: [
@@ -419,6 +419,58 @@
         search: {
             regex: true,
         },
+        fnInitComplete: function(oSettings, json) {
+            if (url === "/rest/server" || url == "/rest/myserver") {
+                // 1. aggregate regions
+                // 2. show panel
+                // 3. create elements
+                var servers = json.Server;
+                if (!servers)
+                    servers = json.MyServer;
+                if (!servers)
+                    return;
+
+                var regions = {};
+                for (const server of servers) {
+                    var region = server.region;
+                    if (region) {
+                        if(!regions[region]) regions[region] = 1
+                        else regions[region] += 1;
+                    }
+                    var extra = server[ "extra regions" ];
+                    if (extra) {
+                        for (const x of extra.split(",")) {
+                            if (x && (!region || region != x)) {
+                                if(!regions[x]) regions[x] = 1
+                                else regions[x] += 1;
+                            }
+                        }
+                    }
+                }
+                if (Object.keys(regions).length < 2) return;
+
+                var panel = document.getElementById("regionspanel");
+                if (!panel) return;
+                var ul = document.getElementById("regionspanelul");
+                if (!ul) return;
+                Object.keys(regions).forEach(function(key) {
+                    var li = document.createElement("li");
+                    // li.className = 'inline-block';
+                    li.style.float = 'left';
+                    li.style.margin = '0 15px';
+                    var a = document.createElement("a");
+                    a.textContent = key + " (" + regions[key] + ")";
+                    if (url == "/rest/myserver") {
+                        a.setAttribute("href", "/app/myserver?region=" + key);
+                    } else {
+                        a.setAttribute("href", "/app/server?region=" + key);
+                    }
+                    li.appendChild(a);
+                    ul.appendChild(li);
+                });
+                panel.style.display = "block";
+            }
+        },
     });
     dataTable.rowData = [];
     dataTable.emptyRow = emptyRow;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/assets/javascripts/browse.js 
new/MirrorCache-1.056/assets/javascripts/browse.js
--- old/MirrorCache-1.052/assets/javascripts/browse.js  2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/assets/javascripts/browse.js  2023-02-09 
09:52:35.000000000 +0100
@@ -1,3 +1,11 @@
+
+function encodeComponentExceptColon(str) {
+  return (
+    encodeURIComponent(str)
+      .replace(/%(3A|2B)/g, (str, hex) => String.fromCharCode(parseInt(hex, 
16)))
+  );
+}
+
 function setupBrowseTable(path) {
     // read columns from empty HTML table rendered by the server
     var columns = [];
@@ -19,9 +27,9 @@
                 }
                 var desc = row['desc'];
                 if (desc) {
-                    data = '<a style="--desc: \'' + desc + '\'" href="' + path 
+ encodeURIComponent(d) + t + '">' + data + '</a>';
+                    data = '<a style="--desc: \'' + desc + '\'" href="' + path 
+ encodeComponentExceptColon(d) + t + '">' + data + '</a>';
                 } else {
-                    data = '<a href="' + path + encodeURIComponent(d) + t + 
'">' + data + '</a>';
+                    data = '<a href="' + path + encodeComponentExceptColon(d) 
+ t + '">' + data + '</a>';
                 }
             }
             if(type === 'sort'){
@@ -42,9 +50,9 @@
             if(type === 'display' && data > 0){
                 data = new Date(data * 1000).toLocaleString().replace(/.\d+$/, 
"").replace(/:\d\d (AM|PM)$/, " $1");
                 if(row['name'].slice(-1) != '/') {
-                    data = '<a href="' + path + 
encodeURIComponent(row['name']) + '.mirrorlist">' + data + '</a>';
+                    data = '<a href="' + path + 
encodeComponentExceptColon(row['name']) + '.mirrorlist">' + data + '</a>';
                 } else {
-                    data = '<a href="' + path + 
encodeURIComponent(row['name'].slice(0,-1)) + '/">' + data + '</a>';
+                    data = '<a href="' + path + 
encodeComponentExceptColon(row['name'].slice(0,-1)) + '/">' + data + '</a>';
                 }
             }
             return data;
@@ -71,7 +79,7 @@
                     } while (Math.round(Math.abs(data) * 10) >= 1024 && u < 
units.length - 1);
                     data = data.toFixed(1) + ' ' + units[u];
                 }
-                data = '<a href="' + path + encodeURIComponent(row['name']) + 
'.mirrorlist">' + data + '</a>';
+                data = '<a href="' + path + 
encodeComponentExceptColon(row['name']) + '.mirrorlist">' + data + '</a>';
             }
             return data;
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/dist/salt/profile/mirrorcache/files/usr/share/mirrorcache/sql/projects.sql
 
new/MirrorCache-1.056/dist/salt/profile/mirrorcache/files/usr/share/mirrorcache/sql/projects.sql
--- 
old/MirrorCache-1.052/dist/salt/profile/mirrorcache/files/usr/share/mirrorcache/sql/projects.sql
    2023-01-12 09:40:42.000000000 +0100
+++ 
new/MirrorCache-1.056/dist/salt/profile/mirrorcache/files/usr/share/mirrorcache/sql/projects.sql
    2023-02-09 09:52:35.000000000 +0100
@@ -5,22 +5,24 @@
 insert into project(name,path) select 'TW source','/source/tumbleweed/repo';
 insert into project(name,path) select 'TW history','/history';
 
-insert into project(name,path) select '15.2 ISO','/distribution/leap/15.2/iso';
-insert into project(name,path) select '15.2 
repo','/distribution/leap/15.2/repo';
-insert into project(name,path) select '15.2 
debug','/debug/distribution/leap/15.2/repo';
-insert into project(name,path) select '15.2 
source','/source/distribution/leap/15.2/repo';
-insert into project(name,path) select '15.2 
update','/update/distribution/leap/15.2';
-
 insert into project(name,path) select '15.3 ISO','/distribution/leap/15.3/iso';
 insert into project(name,path) select '15.3 
repo','/distribution/leap/15.3/repo';
 insert into project(name,path) select '15.3 
debug','/debug/distribution/leap/15.3/repo';
 insert into project(name,path) select '15.3 
source','/source/distribution/leap/15.3/repo';
-insert into project(name,path) select '15.3 
update','/update/distribution/leap/15.3';
+insert into project(name,path) select '15.3 update','/update/leap/15.3';
 insert into project(name,path) select '15.3 
port','/ports/aarch64/distribution/leap/15.3';
 
 insert into project(name,path) select '15.4 ISO','/distribution/leap/15.4/iso';
 insert into project(name,path) select '15.4 
repo','/distribution/leap/15.4/repo';
 insert into project(name,path) select '15.4 
debug','/debug/distribution/leap/15.4/repo';
 insert into project(name,path) select '15.4 
source','/source/distribution/leap/15.4/repo';
-insert into project(name,path) select '15.4 
update','/update/distribution/leap/15.4';
+insert into project(name,path) select '15.4 update','/update/leap/15.4';
 insert into project(name,path) select '15.4 
port','/ports/aarch64/distribution/leap/15.4';
+
+insert into project(name,path) select '15.5 ISO','/distribution/leap/15.5/iso';
+insert into project(name,path) select '15.5 
repo','/distribution/leap/15.5/repo';
+insert into project(name,path) select '15.5 
debug','/debug/distribution/leap/15.5/repo';
+insert into project(name,path) select '15.5 
source','/source/distribution/leap/15.5/repo';
+insert into project(name,path) select '15.5 update','/update/leap/15.5';
+insert into project(name,path) select '15.5 
port','/ports/aarch64/distribution/leap/15.5';
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/lib/MirrorCache/Config.pm 
new/MirrorCache-1.056/lib/MirrorCache/Config.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Config.pm     2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Config.pm     2023-02-09 
09:52:35.000000000 +0100
@@ -39,6 +39,8 @@
 
 has plugin_status => $ENV{MIRRORCACHE_PLUGIN_STATUS};
 
+has mirror_provider       => $ENV{MIRRORCACHE_MIRROR_PROVIDER};
+
 has db_provider           => undef;
 has custom_footer_message => $ENV{MIRRORCACHE_CUSTOM_FOOTER_MESSAGE};
 
@@ -50,7 +52,7 @@
     my $cfg;
     $cfg = Config::IniFiles->new(-file => $cfgfile, -fallback => 'default') if 
$cfgfile;
     if ($cfg) {
-        for my $k (qw/root redirect browser_agent_mask/) {
+        for my $k (qw/root redirect mirror_provider browser_agent_mask/) {
             if (my $v = $cfg->val('default', $k)) {
                 $self->$k($v);
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/lib/MirrorCache/Datamodule.pm 
new/MirrorCache-1.056/lib/MirrorCache/Datamodule.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Datamodule.pm 2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Datamodule.pm 2023-02-09 
09:52:35.000000000 +0100
@@ -46,6 +46,7 @@
 has [ 'torrent', 'magnet', 'btih' ];
 has [ 'json', 'jsontable' ];
 has [ 'folder_id', 'file_id', 'file_age', 'folder_sync_last', 
'folder_scan_last' ]; # shortcut to requested folder and file, if known
+has [ 'real_folder_id' ];
 
 has root_country => ($ENV{MIRRORCACHE_ROOT_COUNTRY} ? 
lc($ENV{MIRRORCACHE_ROOT_COUNTRY}) : "");
 has '_root_region';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/Hash.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/Hash.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/Hash.pm 2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/Hash.pm 2023-02-09 
09:52:35.000000000 +0100
@@ -26,6 +26,8 @@
   { data_type => "char", size => 40 },
   "sha256",
   { data_type => "char", size => 64 },
+  "sha512",
+  { data_type => "char", size => 128 },
   "piece_size",
   { data_type => "int" },
   "pieces",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/MyServer.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/MyServer.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/MyServer.pm     
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/MyServer.pm     
2023-02-09 09:52:35.000000000 +0100
@@ -44,6 +44,11 @@
 
 __PACKAGE__->set_primary_key("id");
 
-# __PACKAGE__->has_many('id' => 'MirrorCache::Schema::Result::ServerAdmin');
+__PACKAGE__->has_many(
+  "server_capability_declaration",
+  "MirrorCache::Schema::Result::ServerCapabilityDeclaration",
+  { "foreign.server_id" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0, join_type => 'left' },
+);
 
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/Redirect.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/Redirect.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/Redirect.pm     
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/Redirect.pm     
2023-02-09 09:52:35.000000000 +0100
@@ -18,7 +18,7 @@
 
 =cut
 
-__PACKAGE__->table("folder");
+__PACKAGE__->table("redirect");
 
 =head1 ACCESSORS
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/Server.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/Server.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/Server.pm       
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/Server.pm       
2023-02-09 09:52:35.000000000 +0100
@@ -58,4 +58,12 @@
   { cascade_copy => 0, cascade_delete => 0 },
 );
 
+
+__PACKAGE__->has_many(
+  "server_capability_declaration",
+  "MirrorCache::Schema::Result::ServerCapabilityDeclaration",
+  { "foreign.server_id" => "self.id" },
+  { cascade_copy => 0, cascade_delete => 0, join_type => 'left' },
+);
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/ServerCapabilityDeclaration.pm
 
new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/ServerCapabilityDeclaration.pm
--- 
old/MirrorCache-1.052/lib/MirrorCache/Schema/Result/ServerCapabilityDeclaration.pm
  2023-01-12 09:40:42.000000000 +0100
+++ 
new/MirrorCache-1.056/lib/MirrorCache/Schema/Result/ServerCapabilityDeclaration.pm
  2023-02-09 09:52:35.000000000 +0100
@@ -40,7 +40,7 @@
         "prefix",
       ],
     },
-    is_nullable => 1,
+    is_nullable => 0,
   },
   enabled => {
       data_type     => 'integer',
@@ -52,4 +52,6 @@
   { data_type => "varchar", is_nullable => 1, size => 256 },
 );
 
+__PACKAGE__->set_primary_key("server_id", "capability");
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/File.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/File.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/File.pm      
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/File.pm      
2023-02-09 09:52:35.000000000 +0100
@@ -96,7 +96,7 @@
 case when coalesce(file.size, 0::bigint)  = 0::bigint and coalesce(hash.size, 
0::bigint)  != 0::bigint then hash.size else file.size end size,
 case when coalesce(file.mtime, 0::bigint) = 0::bigint and coalesce(hash.mtime, 
0::bigint) != 0::bigint then hash.mtime else file.mtime end mtime,
 coalesce(hash.target, file.target) target,
-file.dt, hash.md5, hash.sha1, hash.sha256, hash.piece_size, hash.pieces,
+file.dt, hash.md5, hash.sha1, hash.sha256, hash.sha512, hash.piece_size, 
hash.pieces,
 (DATE_PART('day',    now() - file.dt) * 24 * 3600 +
  DATE_PART('hour',   now() - file.dt) * 3600 +
  DATE_PART('minute', now() - file.dt) * 60 +
@@ -119,7 +119,7 @@
 case when coalesce(file.size, 0)  = 0 and coalesce(hash.size, 0)  != 0 then 
hash.size else file.size end size,
 case when coalesce(file.mtime, 0) = 0 and coalesce(hash.mtime, 0) != 0 then 
hash.mtime else file.mtime end mtime,
 coalesce(hash.target, file.target) target,
-file.dt, hash.md5, hash.sha1, hash.sha256, hash.piece_size, hash.pieces,
+file.dt, hash.md5, hash.sha1, hash.sha256, hash.sha512, hash.piece_size, 
hash.pieces,
 TIMESTAMPDIFF(SECOND, file.dt, CURRENT_TIMESTAMP(3)) as age
 from file
 left join hash on file_id = id and
@@ -172,7 +172,7 @@
 case when coalesce(file.size, 0::bigint)  = 0::bigint and coalesce(hash.size, 
0::bigint)  != 0::bigint then hash.size else file.size end size,
 case when coalesce(file.mtime, 0::bigint) = 0::bigint and coalesce(hash.mtime, 
0::bigint) != 0::bigint then hash.mtime else file.mtime end mtime,
 coalesce(hash.target, file.target) target,
-file.dt, hash.md5, hash.sha1, hash.sha256, hash.piece_size, hash.pieces,
+file.dt, hash.md5, hash.sha1, hash.sha256, hash.sha512, hash.piece_size, 
hash.pieces,
 hash.zlengths, hash.zblock_size, hash.zhashes,
 (DATE_PART('day',    now() - file.dt) * 24 * 3600 +
  DATE_PART('hour',   now() - file.dt) * 3600 +
@@ -194,7 +194,7 @@
 case when coalesce(file.size, 0)  = 0 and coalesce(hash.size, 0)  != 0 then 
hash.size else file.size end size,
 case when coalesce(file.mtime, 0) = 0 and coalesce(hash.mtime, 0) != 0 then 
hash.mtime else file.mtime end mtime,
 coalesce(hash.target, file.target) target,
-file.dt, hash.md5, hash.sha1, hash.sha256, hash.piece_size, hash.pieces,
+file.dt, hash.md5, hash.sha1, hash.sha256, hash.sha512, hash.piece_size, 
hash.pieces,
 hash.zlengths, hash.zblock_size, hash.zhashes,
 TIMESTAMPDIFF(SECOND, file.dt, CURRENT_TIMESTAMP(3)) as age
 from file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/Folder.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/Folder.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/Folder.pm    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/Folder.pm    
2023-02-09 09:52:35.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright (C) 2020 SUSE LLC
+# Copyright (C) 2020-2023 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
@@ -171,13 +171,14 @@
     my $dbh     = $schema->storage->dbh;
 
     my $sql = <<'END_SQL';
-select id, sync_last, scan_last, '' as pathto
+select id, sync_last, scan_last, '' as pathto, path
 from folder
 where path = ?
 union
-select id, NULL, NULL, pathto
-from redirect
+select folder.id, sync_last, scan_last, pathto, path
+from redirect left join folder on pathto = path
 where pathfrom = ?
+order by pathto desc
 limit 1
 END_SQL
     my $prep = $dbh->prepare($sql);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/Hash.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/Hash.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/Hash.pm      
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/Hash.pm      
2023-02-09 09:52:35.000000000 +0100
@@ -22,7 +22,7 @@
 use DBI qw(:sql_types);
 
 sub store {
-    my ($self, $file_id, $mtime, $size, $md5hex, $sha1hex, $sha256hex, 
$block_size, $pieceshex, $zlengths, $zblock_size, $zhashes, $target) = @_;
+    my ($self, $file_id, $mtime, $size, $md5hex, $sha1hex, $sha256hex, 
$sha512hex, $block_size, $pieceshex, $zlengths, $zblock_size, $zhashes, 
$target) = @_;
 
     my $rsource = $self->result_source;
     my $schema  = $rsource->schema;
@@ -31,14 +31,15 @@
     my $sql;
 if ($dbh->{Driver}->{Name} eq 'Pg') {
     $sql = <<'END_SQL';
-insert into hash(file_id, mtime, size, md5, sha1, sha256, piece_size, pieces, 
zlengths, zblock_size, zhashes, target, dt)
-values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, now())
+insert into hash(file_id, mtime, size, md5, sha1, sha256, sha512, piece_size, 
pieces, zlengths, zblock_size, zhashes, target, dt)
+values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, now())
 ON CONFLICT (file_id) DO UPDATE
   SET size   = excluded.size,
       mtime  = excluded.mtime,
       md5    = excluded.md5,
       sha1   = excluded.sha1,
       sha256 = excluded.sha256,
+      sha512 = excluded.sha512,
       piece_size  = excluded.piece_size,
       pieces      = excluded.pieces,
       zlengths    = excluded.zlengths,
@@ -49,14 +50,15 @@
 END_SQL
 } else {
     $sql = <<'END_SQL';
-insert into hash(file_id, mtime, size, md5, sha1, sha256, piece_size, pieces, 
zlengths, zblock_size, zhashes, target, dt)
-values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP(3))
+insert into hash(file_id, mtime, size, md5, sha1, sha256, sha512, piece_size, 
pieces, zlengths, zblock_size, zhashes, target, dt)
+values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP(3))
 ON DUPLICATE KEY UPDATE
       size   = values(size),
       mtime  = values(mtime),
       md5    = values(md5),
       sha1   = values(sha1),
       sha256 = values(sha256),
+      sha512 = values(sha512),
       piece_size  = values(piece_size),
       pieces      = values(pieces),
       zlengths    = values(zlengths),
@@ -73,12 +75,13 @@
     $prep->bind_param( 4, $md5hex,      SQL_CHAR);
     $prep->bind_param( 5, $sha1hex,     SQL_CHAR);
     $prep->bind_param( 6, $sha256hex,   SQL_CHAR);
-    $prep->bind_param( 7, $block_size,  SQL_INTEGER);
-    $prep->bind_param( 8, $pieceshex,   SQL_VARCHAR);
-    $prep->bind_param( 9, $zlengths,    SQL_VARCHAR);
-    $prep->bind_param(10, $zblock_size, SQL_INTEGER);
-    $prep->bind_param(11, $zhashes,     SQL_VARBINARY); # we must force 
varbinary, otherwise driver will corrupt hashes trying to handle unicode
-    $prep->bind_param(12, $target,      SQL_VARCHAR);
+    $prep->bind_param( 7, $sha512hex,   SQL_CHAR);
+    $prep->bind_param( 8, $block_size,  SQL_INTEGER);
+    $prep->bind_param( 9, $pieceshex,   SQL_VARCHAR);
+    $prep->bind_param(10, $zlengths,    SQL_VARCHAR);
+    $prep->bind_param(11, $zblock_size, SQL_INTEGER);
+    $prep->bind_param(12, $zhashes,     SQL_VARBINARY); # we must force 
varbinary, otherwise driver will corrupt hashes trying to handle unicode
+    $prep->bind_param(13, $target,      SQL_VARCHAR);
     $prep->execute();
 }
 
@@ -97,7 +100,7 @@
     }
 
     my $sql = <<"END_SQL";
-select file.name, hash.mtime, hash.size, md5, sha1, sha256, piece_size, 
pieces, hash.target, hash.dt
+select file.name, hash.mtime, hash.size, md5, sha1, sha256, sha512, 
piece_size, pieces, hash.target, hash.dt
 from hash left join file on file_id = id
 where file_id in ( select id from file where folder_id = ? )
 $time_constraint_condition limit 100000
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/Server.pm 
new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/Server.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Schema/ResultSet/Server.pm    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Schema/ResultSet/Server.pm    
2023-02-09 09:52:35.000000000 +0100
@@ -323,4 +323,34 @@
     return $server_arrayref;
 }
 
+sub check_sync {
+    my ($self, $h) = @_;
+
+    my $rsource = $self->result_source;
+    my $schema  = $rsource->schema;
+    my $dbh     = $schema->storage->dbh;
+
+    my $sql = 'select * from server where id = ?';
+    my $exist = $dbh->selectrow_hashref($sql, undef, $h->{id});
+
+    unless ($exist) {
+        $sql = 'insert into server(id, hostname, urldir, enabled, region, 
country, score, lat, lng) select ?, ?, ?, ?, ?, ?, ?, ?, ?';
+        $dbh->prepare($sql)->execute($h->{id}, $h->{hostname}, $h->{urldir}, 
$h->{enabled}, $h->{region}, $h->{country}, $h->{score}, $h->{lat}, $h->{lng});
+        return 2;
+    }
+
+    return 0 if $exist->{hostname} ne $h->{hostname};
+
+    my $eq = 1;
+    for my $key (qw(urldir enabled region country score lat lng)) {
+        next if ($exist->{$key} // '') eq ($h->{$key} // '');
+        $eq = 0;
+        last;
+    }
+    return 1 if $eq;
+    $sql = 'update server set urldir = ?, enabled = ?, region = ?, country = 
?, score = ?, lat = ?, lng = ? where id = ? and hostname = ?';
+    $dbh->prepare($sql)->execute($h->{urldir}, $h->{enabled}, $h->{region}, 
$h->{country}, $h->{score}, $h->{lat}, $h->{lng}, $h->{id}, $h->{hostname});
+    return 3;
+}
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/lib/MirrorCache/Task/Cleanup.pm 
new/MirrorCache-1.056/lib/MirrorCache/Task/Cleanup.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Task/Cleanup.pm       2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Task/Cleanup.pm       2023-02-09 
09:52:35.000000000 +0100
@@ -38,11 +38,11 @@
     my $sql;
     if ($schema->pg) {
 $sql = <<'END_SQL';
-update minion_jobs set state = 'failed', result = concat("killed; old result: 
", result) where state = 'active' and started < now() - interval '1 hour'
+update minion_jobs set state = 'failed', result = '"killed"' where state = 
'active' and started < now() - interval '1 hour'
 END_SQL
     } else {
 $sql = <<'END_SQL';
-update minion_jobs set state = 'failed', result = concat_ws("", "killed; old 
result: ", result) where state = 'active' and started < now() - interval 2 hour
+update minion_jobs set state = 'failed', result = '"killed"' where state = 
'active' and started < now() - interval 1 hour
 END_SQL
 }
     eval {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Task/FolderHashesCreate.pm 
new/MirrorCache-1.056/lib/MirrorCache/Task/FolderHashesCreate.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Task/FolderHashesCreate.pm    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Task/FolderHashesCreate.pm    
2023-02-09 09:52:35.000000000 +0100
@@ -91,13 +91,14 @@
             $target = $dest->basename if $dest->dirname eq '.' || 
$dest->dirname eq "$indir$path";
         }
     };
-    return $schema->resultset('Hash')->store($file_id, undef, 0, undef, undef, 
undef, undef, undef, undef, undef, undef, $target) if $target;
+    return $schema->resultset('Hash')->store($file_id, undef, 0, undef, undef, 
undef, undef, undef, undef, undef, undef, undef, $target) if $target;
 
     open my $fh, "<", $f or die "Unable to open $f!";
     my $stat = stat($fh);
     my $mtime = $stat->mtime;
     my $d1   = Digest::SHA->new(1);
     my $d256 = Digest::SHA->new(256);
+    my $d512 = Digest::SHA->new(512);
     my $dmd5 = Digest::MD5->new;
     my @pieces;
     my $data;
@@ -117,6 +118,7 @@
 
         $d1->add($data);
         $d256->add($data);
+        $d512->add($data);
         $dmd5->add($data);
     }
     close $fh;
@@ -127,7 +129,7 @@
         $zsync_block_size = $zsync->block_size;
         $zsync_hashes     = $zsync->digest;
     }
-    $schema->resultset('Hash')->store($file_id, $mtime, $size, 
$dmd5->hexdigest, $d1->hexdigest, $d256->hexdigest, $block_size, $pieceshex, 
$zsync_lengths, $zsync_block_size, $zsync_hashes);
+    $schema->resultset('Hash')->store($file_id, $mtime, $size, 
$dmd5->hexdigest, $d1->hexdigest, $d256->hexdigest, $d512->hexdigest, 
$block_size, $pieceshex, $zsync_lengths, $zsync_block_size, $zsync_hashes);
 }
 
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Task/FolderHashesImport.pm 
new/MirrorCache-1.056/lib/MirrorCache/Task/FolderHashesImport.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Task/FolderHashesImport.pm    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Task/FolderHashesImport.pm    
2023-02-09 09:52:35.000000000 +0100
@@ -73,7 +73,7 @@
         eval {
             $rsHash = $schema->resultset('Hash') unless $rsHash;
             $rsHash->store($file->id, $hash->{mtime}, $hash->{size}, 
$hash->{md5},
-                $hash->{sha1}, $hash->{sha256}, $hash->{piece_size}, 
$hash->{pieces}, undef, undef, undef, $hash->{target});
+                $hash->{sha1}, $hash->{sha256}, $hash->{sha512}, 
$hash->{piece_size}, $hash->{pieces}, undef, undef, undef, $hash->{target});
             if (my $hdt = $hash->{dt}) {
                 my $hDt = Mojo::Date->new($hdt);
                 $last_import = $hDt if !$last_import || ( $hdt && 
$last_import->epoch < $hDt->epoch);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/lib/MirrorCache/Task/FolderSync.pm 
new/MirrorCache-1.056/lib/MirrorCache/Task/FolderSync.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Task/FolderSync.pm    2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Task/FolderSync.pm    2023-02-09 
09:52:35.000000000 +0100
@@ -153,7 +153,7 @@
         if ($dbfileids{$file}) {
             my $id = delete $dbfileidstodelete{$file};
             if (
-                (defined $size && defined $mtime) && ($size != 
$dbfilesizes{$file} || $mtime != $dbfilemtimes{$file})
+                (defined $size && defined $mtime) && ($size != 
($dbfilesizes{$file} // -1) || $mtime != ($dbfilemtimes{$file} // -1))
                 ||
                 (defined $target && $target ne ($dbfiletargets{$file} // ''))
             ) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/Task/MirrorProviderSync.pm 
new/MirrorCache-1.056/lib/MirrorCache/Task/MirrorProviderSync.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Task/MirrorProviderSync.pm    
1970-01-01 01:00:00.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Task/MirrorProviderSync.pm    
2023-02-09 09:52:35.000000000 +0100
@@ -0,0 +1,70 @@
+# Copyright (C) 2023 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::MirrorProviderSync;
+use Mojo::Base 'Mojolicious::Plugin';
+use Mojo::JSON qw(decode_json);
+use MirrorCache::Utils 'datetime_now';
+
+sub register {
+    my ($self, $app) = @_;
+    $app->minion->add_task(mirror_provider_sync => sub { _run($app, @_) });
+}
+
+my $DELAY = int($ENV{MIRRORCACHE_MIRROR_PROVIDER_SYNC_RETRY_INTERVAL} // 10 * 
60);
+
+sub _run {
+    my ($app, $job, $once) = @_;
+    my $minion = $app->minion;
+
+    return $job->finish('No mirror provider configured')
+        unless my $mirror_provider = $app->mcconfig->mirror_provider;
+
+    return $job->finish('Previous job is still active')
+        unless my $guard = $minion->guard('mirror_provider_sync', 300);
+
+    # getting list of mirrors to sync
+    my $ua = Mojo::UserAgent->new->max_redirects(10);
+
+    my $url = $mirror_provider;
+    my $got = $ua->get($url)->result;
+
+    return $job->fail('Request to MIRROR_PROVIDER ' . $url . ' failed, 
response code ' . $got->code)
+        if $got->code > 299;
+
+    my $server_list = $got->json;
+
+    return $job->fail('Failed to interpret json as array in MIRROR_PROVIDER 
request:' . $url)
+        unless ref $server_list eq 'ARRAY' && @$server_list;
+
+    my $schema = $app->schema;
+    my $rsServer = $schema->resultset('Server');
+
+    for my $server (@$server_list) {
+        next unless $server->{hostname} && $server->{id};
+
+        my $fail = 1;
+        my $res = $rsServer->check_sync($server);
+        unless ($res) {
+            $job->note($server->{hostname} => 'Failed to sync ' . 
datetime_now) ;
+        } elsif ($res > 1) {
+            $job->note($server->{hostname} => 'Synced ' . datetime_now) ;
+        }
+    }
+
+    return $job->retry({delay => $DELAY}) unless $once;
+}
+
+1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/lib/MirrorCache/Task/MirrorScan.pm 
new/MirrorCache-1.056/lib/MirrorCache/Task/MirrorScan.pm
--- old/MirrorCache-1.052/lib/MirrorCache/Task/MirrorScan.pm    2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/Task/MirrorScan.pm    2023-02-09 
09:52:35.000000000 +0100
@@ -52,7 +52,7 @@
         return $job->finish('folder sync job is still active')
             unless my $guard_r = $minion->guard('folder_sync' . $path, 360);
 
-        ($folder_id, $realfolder_id, $anotherpath, $latestdt, $max_dt, 
$dbfiles, $dbfileids, $dbfileprefixes) 
+        ($folder_id, $realfolder_id, $anotherpath, $latestdt, $max_dt, 
$dbfiles, $dbfileids, $dbfileprefixes)
             = _dbfiles($app, $job, $path);
     }
     return undef unless $dbfiles;
@@ -68,7 +68,13 @@
     my $schema = $app->schema;
     my $folder = $schema->resultset('Folder')->find({path => $path});
     return undef unless $folder && $folder->id; # folder is not added to db yet
-    my $realpath = $app->mc->root->realpath($path);
+    my $realpath;
+    if ($app->mc->root->is_remote && !$ENV{MIRRORCACHE_ROOT_NFS}) {
+        my $redirect = $schema->resultset('Redirect')->find({pathfrom => 
$path});
+        $realpath = $redirect->pathto if $redirect;
+    } else {
+        $realpath = $app->mc->root->realpath($path);
+    }
     my $realfolder = $schema->resultset('Folder')->find({path => $realpath}) 
if $realpath;
     # we collect max(dt) here to avoid race with new files added to DB
     my $latestdt = $schema->resultset('File')->find({folder_id => $realfolder? 
$realfolder->id : $folder->id}, {
@@ -121,6 +127,7 @@
             my $sid = $folder_on_mirror->{server_id};
             if ($tx->result->code > 399 ) {
                 my $sql = 'delete from folder_diff_server where server_id = ? 
and folder_diff_id in (select id from folder_diff where folder_id = ?)';
+                $sql = 'delete folder_diff_server from folder_diff_server join 
folder_diff on folder_diff_id = id where server_id = ? and folder_id = ?' 
unless $schema->pg; # otherwise mariadb is bad at execution plan
                 eval {
                     $schema->storage->dbh->prepare($sql)->execute($sid, 
$folder_id);
                     1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Controller/Rest/ServerLocation.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Controller/Rest/ServerLocation.pm
--- 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Controller/Rest/ServerLocation.pm  
    2023-01-12 09:40:42.000000000 +0100
+++ 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Controller/Rest/ServerLocation.pm  
    2023-02-09 09:52:35.000000000 +0100
@@ -36,4 +36,21 @@
     );
 }
 
+sub list {
+    my ($self) = @_;
+
+    my $region = $self->param("region");
+
+    return $self->render(code => 501, text => 'Expected parameter "region"') 
unless $region;
+
+    my $sql = "select * from server where region = ? or exists( select 1 from 
server_capability_declaration where server_id = server.id and capability = 
'region' and concat(',', extra, ',') like concat('%',?::text,'%'));";
+
+    $sql =~ s/::text//g unless $self->schema->pg;
+
+
+    my $res = $self->schema->storage->dbh->selectall_arrayref($sql, {Columns 
=> {}}, $region, $region);
+
+    return $self->render(json => $res);
+}
+
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Controller/Rest/Table.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Controller/Rest/Table.pm
--- old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Controller/Rest/Table.pm       
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Controller/Rest/Table.pm       
2023-02-09 09:52:35.000000000 +0100
@@ -24,13 +24,13 @@
 my %tables = (
     Server => {
         keys     => [['id'], ['hostname'],],
-        cols     => ['id', 'sponsor', 'sponsor url', 'hostname', 'urldir', 
'enabled', 'region', 'country', 'comment', 'public notes'],
+        cols     => ['id', 'sponsor', 'sponsor url', 'hostname', 'urldir', 
'enabled', 'region', 'extra regions', 'country', 'comment', 'public notes'],
         required => ['id', 'hostname', 'urldir'],
         defaults => {urldir => '', sponsor => '', 'sponsor_url' => ''},
     },
     MyServer => {
         keys     => [['id'], ['hostname'],],
-        cols     => ['id', 'sponsor', 'sponsor url', 'hostname', 'urldir', 
'enabled', 'region', 'country', 'comment', 'public notes'],
+        cols     => ['id', 'sponsor', 'sponsor url', 'hostname', 'urldir', 
'enabled', 'region', 'extra regions', 'country', 'comment', 'public notes'],
         required => ['id', 'hostname', 'urldir'],
         defaults => {urldir => '', sponsor => '', 'sponsor_url' => ''},
     },
@@ -51,6 +51,41 @@
 
     my $table = $self->param("table");
     my %search;
+    my %x;
+    my $region = $self->req->param('region');
+
+    if ($table eq 'Server' || $table eq 'MyServer') {
+        %x = (
+                        join => 'server_capability_declaration',
+                        '+select' => [ 'server_capability_declaration.extra' ],
+                        '+as'     => [ 'extra_regions' ],
+              );
+
+        my $a       = 'region';
+        my $pattern = '(^|,)' . $region . '(,|$)';
+        my $regexp  = $self->schema->pg ? '~' : 'REGEXP';
+        my $isnull  = "IS NULL";
+        unless ($region) {
+            $search{'-or'} = [
+                [ "server_capability_declaration.capability" => $a ],
+                [ "server_capability_declaration.capability" => \$isnull ]
+            ];
+
+        } else {
+            $search{'-and'} = [
+                '-or'  => [
+                    [ "server_capability_declaration.capability" => $a ],
+                    [ "server_capability_declaration.capability" => \$isnull ]
+                ],
+                '-or'  => [
+                    'region' => $region,
+                    'server_capability_declaration.extra' => { $regexp, 
$pattern }
+                ]
+            ];
+        }
+        $x{join} = [ 'server_admin', 'server_capability_declaration' ] if 
$table eq 'MyServer';
+    }
+
 
     for my $key (@{$tables{$table}->{keys}}) {
         my $have = 1;
@@ -68,16 +103,11 @@
     eval {
         unless (_myserver($self->req)) {
             my $rs = $self->schema->resultset($table);
-            @result = %search ? $rs->search(\%search) : $rs->all;
+            @result = $rs->search(%search ? \%search : {}, %x? \%x : {});
         } else {
             my $rs = $self->schema->resultset('Server');
             $search{username} = $self->current_username;
-            @result = %search ? $rs->search(
-                \%search,
-                {
-                    join => 'server_admin',
-                }
-            ) : $rs->all;
+            @result = $rs->search(\%search, \%x);
         }
     };
     my $error = $@;
@@ -121,6 +151,8 @@
     my $error;
     my $id;
 
+    my $extra_regions = delete $entry{'extra_regions'};
+
     try { $id = $self->schema->resultset($table)->create(\%entry)->id; } catch 
{ $error = shift; };
 
     if ($error) {
@@ -128,6 +160,12 @@
     }
     try { $self->schema->resultset('ServerAdmin')->create({server_id => $id, 
username => $username}); } catch { $error = shift; } if _myserver($self->req);
 
+    try { 
$self->schema->resultset('ServerCapabilityDeclaration')->create({server_id => 
$id, capability => 'region', enabled => 1, extra => $extra_regions}); } catch { 
$error = shift; } if $extra_regions;
+
+    if ($error) {
+        return $self->render(json => {error => $error}, status => 400);
+    }
+
     my %event_data;
     for my $k (keys %entry) {
         next if !$entry{$k} or "$entry{$k}" eq '';
@@ -168,6 +206,7 @@
             my @event_data;
             for my $k (keys %{ $entry }) {
                 next if !$entry->{$k} || ("$entry->{$k}" eq '' && (!$rc->$k || 
$rc->$k . '' eq ''));
+                next if $k eq 'extra_regions';
                 if (!$rc->$k or $rc->$k . '' eq '') {
                     push @event_data, {"new $k" => $entry->{$k}};
                 } elsif ($entry->{$k} ne $rc->$k) {
@@ -178,7 +217,18 @@
             }
             my $name = 'mc_' . lc $table . '_update';
             $self->emit_event($name, \@event_data, $self->current_user->id);
+            my $extra_regions = delete $entry->{'extra_regions'};
             $rc->update($entry);
+            if ($table eq 'Server' || $table eq 'MyServer') {
+                my $xrc = 
$schema->resultset('ServerCapabilityDeclaration')->find({server_id => 
$self->param('id'), capability => 'region'});
+                unless ($xrc) {
+                    
$schema->resultset('ServerCapabilityDeclaration')->create({server_id => 
$self->param('id'), capability => 'region', enabled => 1, extra => 
$extra_regions}) if $extra_regions;
+                } elsif ($extra_regions && $extra_regions ne ($xrc->extra // 
'')) {
+                    $xrc->update({ extra => $extra_regions });
+                } elsif ($xrc->extra && !$extra_regions) {
+                    $xrc->delete;
+                }
+            }
             $ret = 1;
         }
         else {
@@ -236,8 +286,10 @@
         $res = $rs->find({id => $self->param('id')});
         if ($res) {
             my %event_data;
-            for my $k (@{$tables{$table}->{cols}}) {
+            for my $c (@{$tables{$table}->{cols}}) {
+                my $k = $c; # without this next line corrupts %tables
                 $k =~ tr/ /_/;
+                next if $k eq 'extra_regions';
                 next if !$res->$k or $res->$k . '' eq '';
                 $event_data{$k} = $res->$k;
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/Backstage.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/Backstage.pm
--- old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/Backstage.pm    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/Backstage.pm    
2023-02-09 09:52:35.000000000 +0100
@@ -47,6 +47,7 @@
         qw(MirrorCache::Task::MirrorScan),
         qw(MirrorCache::Task::MirrorLocation),
         qw(MirrorCache::Task::MirrorProbe),
+        qw(MirrorCache::Task::MirrorProviderSync),
         qw(MirrorCache::Task::FolderHashesCreate),
         qw(MirrorCache::Task::FolderHashesImport),
         qw(MirrorCache::Task::FolderSyncScheduleFromMisses),
@@ -60,6 +61,9 @@
     if (defined $ENV{MIRRORCACHE_PERMANENT_JOBS}) {
         @permanent_jobs = split /[:,\s]+/, $ENV{MIRRORCACHE_PERMANENT_JOBS};
     }
+    if ($app->mcconfig->mirror_provider) {
+        push @permanent_jobs, 'mirror_provider_sync';
+    }
 }
 
 sub register {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/Dir.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/Dir.pm
--- old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/Dir.pm  2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/Dir.pm  2023-02-09 
09:52:35.000000000 +0100
@@ -143,7 +143,8 @@
     my $rsFolder = shift;
     my $c = $dm->c;
 
-    my $folder_id = $dm->folder_id;
+    my $folder_id = $dm->real_folder_id;
+    $folder_id = $dm->folder_id unless $folder_id;
     unless ($folder_id) {
         $rsFolder  = $c->app->schema->resultset('Folder') unless $rsFolder;
         if (my $folder = $rsFolder->find({path => $dm->root_subtree . $dir})) {
@@ -180,7 +181,7 @@
         }
 
         $c->log->error('pedantic: ' . ($dm->pedantic // 'undef')) if $MCDEBUG;
-        if ($path =~ m/.*(Media|Current)\.iso(\.sha256(\.asc)?)?/ && 
$dm->pedantic) {
+        if ($path =~ 
m/(GNOME_.*|.*(Media|Current|Next))\.iso(\.sha256(\.asc)?)?/ && $dm->pedantic) {
             my $ln = $root->detect_ln_in_the_same_folder($path);
             $c->log->error("ln for $path : " . ($ln // 'null')) if $MCDEBUG;
             if ($ln) {
@@ -280,6 +281,11 @@
     return _render_top_folders($dm) if $ENV{MIRRORCACHE_TOP_FOLDERS} && $path 
eq '/';
     return $root->render_file_if_nfs($dm, $path) if $root->is_remote;
 
+    # root is only local now
+    if (defined($dm->c->param('realpath'))) {
+        my $realpath = $root->realpath($path);
+        return $dm->redirect($dm->route . $realpath . '/') if $realpath;
+    }
     if ($root->is_dir($path)) {
         return $dm->redirect($dm->route . $path . '/') if !$trailing_slash && 
$path ne '/';
         return _render_dir($dm, $path);
@@ -297,30 +303,47 @@
 
     my $file_pattern_in_folder = $trailing_slash && ($dm->regex || $dm->glob) 
&& ($dm->metalink || $dm->meta4 || $dm->mirrorlist);
     $c->log->error($c->dumper('$file_pattern_in_folder', 
$file_pattern_in_folder)) if $MCDEBUG;
-    if ( (!$trailing_slash && $path ne '/') || $file_pattern_in_folder ) {
+    my $it_must_be_folder = ( $trailing_slash || $path eq '/');
+    my $folder_or_pattern = $it_must_be_folder || $file_pattern_in_folder;
+    { # this bracked to simplify diff
         my $f = Mojo::File->new($path);
-        my $dirname = ($file_pattern_in_folder? $path : $f->dirname);
+        my $dirname = ($folder_or_pattern? $path : $f->dirname);
         $dirname = $root->realpath($dirname);
-        $dirname = $dm->root_subtree . ($file_pattern_in_folder? $path : 
$f->dirname) unless $dirname;
-        $c->log->error($c->dumper('dirname:', $dirname)) if $MCDEBUG;
-        if (my $parent_folder = $rsFolder->find({path => $dirname})) {
-            my $realpath_subtree = $root->realpath($dm->root_subtree . 
($file_pattern_in_folder? $path : $f->dirname)) // $dirname;
+        $dirname = $dm->root_subtree . ($folder_or_pattern? $path : 
$f->dirname) unless $dirname;
+        $c->log->error($c->dumper('dirname:', $dirname, 'path:', $path, 
'trail:', $trailing_slash)) if $MCDEBUG;
+        if (my $parent_folder = $rsFolder->find_folder_or_redirect($dirname)) {
+            my $realpath_subtree;
+            if ($root->is_remote && $parent_folder && $parent_folder->{path} 
ne $dirname) {
+                $realpath_subtree = $parent_folder->{path};
+            } else {
+                $realpath_subtree = $root->realpath($dm->root_subtree . 
($folder_or_pattern? $path : $f->dirname)) // $dirname;
+            }
             if ($dirname eq $realpath_subtree) {
-                if ($dirname eq $f->dirname || $file_pattern_in_folder) {
-                    $dm->folder_id($parent_folder->id);
-                    $dm->folder_sync_last($parent_folder->sync_last);
-                    $dm->folder_scan_last($parent_folder->scan_last);
+                if ($dirname eq $f->dirname || $folder_or_pattern) {
+                    $dm->folder_id($parent_folder->{id});
+                    $dm->folder_sync_last($parent_folder->{sync_last});
+                    $dm->folder_scan_last($parent_folder->{scan_last});
                 }
             } else {
                 my $another_folder = $rsFolder->find({path => 
$dm->root_subtree . $f->dirname});
-                $c->log->error($c->dumper('another_folder:', $another_folder)) 
if $MCDEBUG;
-                return undef unless $another_folder; # nothing found, proceed 
to _guess_what_to_render
+                $c->log->error($c->dumper('another_folder:', 
$another_folder->{id})) if $MCDEBUG;
+                return undef unless $another_folder || $it_must_be_folder; # 
nothing found, proceed to _guess_what_to_render
+                if ($parent_folder) {
+                    $dm->real_folder_id($parent_folder->{id});
+                    $dm->folder_id($another_folder->{id}) if $another_folder;
+                    $dm->folder_sync_last($parent_folder->{sync_last});
+                    $dm->folder_scan_last($parent_folder->{scan_last});
+                }
+            }
+            if ($it_must_be_folder && !$file_pattern_in_folder) {
+                $dm->real_folder_id($parent_folder->{id});
+                return _render_dir($dm, $path, $rsFolder);
             }
             my $xtra = '';
             $xtra = '.zsync' if $dm->zsync && !$dm->accept_zsync;
             my $file;
-            $c->log->error($c->dumper('parent_folder:', $parent_folder->path)) 
if $MCDEBUG;
-            $file = 
$schema->resultset('File')->find_with_hash($parent_folder->id, $f->basename, 
$xtra, $dm->regex, $dm->glob_regex) if $parent_folder;
+            $c->log->error($c->dumper('parent_folder:', 
$parent_folder->{path})) if $MCDEBUG && $parent_folder;
+            $file = 
$schema->resultset('File')->find_with_hash($parent_folder->{id}, $f->basename, 
$xtra, $dm->regex, $dm->glob_regex) if $parent_folder;
             $c->log->error($c->dumper('file:', $f->basename, $file)) if 
$MCDEBUG;
 
             # folders are stored with trailing slash in file table, so they 
will not be selected here
@@ -333,11 +356,6 @@
                     $path = $path . '.zsync';
                 }
 
-                $c->log->error($c->dumper('file_size: ', $file->{size} // 
'undef', 'huge_file_size: ', $mc_config->huge_file_size)) if $MCDEBUG;
-                if ($root->is_remote && !$dm->extra && $file->{size} && 
$mc_config->redirect_huge && $mc_config->huge_file_size <= $file->{size}) {
-                    $dm->redirect($dm->scheme . '://' . 
$mc_config->redirect_huge . $path);
-                    return 1;
-                }
                 if ($file->{target}) {
                     # redirect to the symlink
                     $dm->redirect($dm->route . $dirname . '/' . 
$file->{target});
@@ -349,16 +367,7 @@
                 return 1;
             }
         }
-    } elsif (my $folder = $rsFolder->find_folder_or_redirect($dm->root_subtree 
. $path)) {
-        $c->log->error('found redirect : ', $folder->{pathto}) if $MCDEBUG && 
$folder->{pathto};
-        return $dm->redirect($folder->{pathto}) if $folder->{pathto};
-        # folder must have trailing slash, otherwise it will be a challenge to 
render links on webpage
-        $dm->folder_id($folder->{id});
-        $dm->folder_sync_last($folder->{sync_last});
-        $dm->folder_scan_last($folder->{scan_last});
-        $dm->file_id(-1);
-        return _render_dir($dm, $path, $rsFolder, $folder) if 
($folder->{sync_last});
-    }
+    } # bracked to simplify diff
     return undef;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm
--- old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm 
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/RenderFileFromMirror.pm 
2023-02-09 09:52:35.000000000 +0100
@@ -1,4 +1,4 @@
-# Copyright (C) 2020-2022 SUSE LLC
+# Copyright (C) 2020-2023 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
@@ -44,7 +44,11 @@
         my $root = $c->mc->root;
         my $f = Mojo::File->new($filepath);
         my $dirname = $f->dirname;
-        my $realdirname = $root->realpath($f->dirname);
+        my $realfolder_id = $dm->real_folder_id;
+        my $realdirname;
+        unless ($realfolder_id) {
+            $realdirname = $root->realpath($f->dirname);
+        }
         $realdirname = $dirname unless $realdirname;
         my $basename = $f->basename;
         $basename = $file->{name} if $file;
@@ -72,8 +76,7 @@
             }
             $schema->resultset('Folder')->set_wanted($folder_id) if 
$need_update;
         }
-        my $realfolder_id = 0;
-        if ($realdirname ne $dirname) {
+        if (!$realfolder_id && $realdirname ne $dirname) {
             my $realfolder = $schema->resultset('Folder')->find({path => 
$realdirname});
             $realfolder_id = $realfolder->id if $realfolder;
             $c->log->error($c->dumper('RENDER FOLDER REAL', $realfolder_id ? 
$realfolder_id : 'NULL')) if $MCDEBUG;
@@ -114,7 +117,7 @@
         my $fullurl; # baseurl with path and filename
         if ($dm->metalink || $dm->meta4 || $dm->torrent || $dm->zsync || 
$dm->magnet) {
            if (!$root->is_remote) {
-                $baseurl = $root->redirect($dm, $dirname); # we must pass 
$path here because it potenially has impact
+                $baseurl = $root->redirect($dm, $filepath); # we must pass 
$path here because it potenially has impact
             } elsif ($file->{size} && $mc_config->redirect_huge && 
$mc_config->huge_file_size <= $file->{size}) {
                 $baseurl = $dm->scheme . '://' . $mc_config->redirect_huge . 
$filepath;
             } else {
@@ -281,6 +284,7 @@
                 md5    => $file->{md5},
                 sha1   => $file->{sha1},
                 sha256 => $file->{sha256},
+                sha512 => $file->{sha512},
             };
 
             my @regions = $c->subsidiary->regions($region, $country);
@@ -309,6 +313,11 @@
         }
 
         unless ($mirror) {
+            if ($root->is_remote && $file->{size} && $mc_config->redirect_huge 
&& $mc_config->huge_file_size <= $file->{size}) {
+                $dm->redirect($dm->scheme . '://' . $mc_config->redirect_huge 
. $filepath);
+                return 1;
+            }
+
             $root->render_file($dm, $filepath);
             return 1;
         }
@@ -448,6 +457,11 @@
         $writer->characters($sha256);
         $writer->endTag('hash');
     }
+    if (my $sha512 = $file->{sha512}) {
+        $writer->startTag('hash', type => 'sha-512');
+        $writer->characters($sha512);
+        $writer->endTag('hash');
+    }
     if (my $piece_size = $file->{piece_size}) {
         $writer->startTag('pieces', length => $piece_size, type => 'sha-1');
         for my $piece (grep {$_} split /(.{40})/, $file->{pieces}) {
@@ -560,7 +574,8 @@
         my $md5 = $file->{md5};
         my $sha1 = $file->{sha1};
         my $sha256 = $file->{sha256};
-        if ($md5 || $sha1 || $sha256) {
+        my $sha512 = $file->{sha512};
+        if ($md5 || $sha1 || $sha256 || $sha512) {
             $writer->startTag('verification');
             if ($md5) {
                 $writer->startTag('hash', type => 'md5');
@@ -577,6 +592,11 @@
                 $writer->characters($sha256);
                 $writer->endTag('hash');
             }
+            if ($sha512) {
+                $writer->startTag('hash', type => 'sha-512');
+                $writer->characters($sha512);
+                $writer->endTag('hash');
+            }
             if (my $piece_size = $file->{piece_size}) {
                 $writer->startTag('pieces', length => $piece_size, type => 
'sha-1');
                 my $piecen = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm
--- old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/RootLocal.pm    
2023-02-09 09:52:35.000000000 +0100
@@ -85,7 +85,7 @@
     } else {
         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);
+        $res = !!$c->render_file(filepath => $rootpath . $root_subtree . 
$filepath, content_type => $dm->mime, content_disposition => 'inline');
     }
     $c->stat->redirect_to_root($dm, $not_miss);
     return $res;
@@ -102,7 +102,7 @@
     eval { $size = -s $full if -f $full; };
     return undef unless ((defined $size) && $size <= $max_size);
     my $c = $dm->c;
-    $c->render_file(filepath => $full, content_type => $dm->mime);
+    $c->render_file(filepath => $full, content_type => $dm->mime, 
content_disposition => 'inline');
     return 1;
 }
 
@@ -161,7 +161,7 @@
 
 sub _detect_ln_in_the_same_folder {
     my ($dir, $file) = @_;
-    return undef unless $file && $file =~ m/.*(Media|Current)\.iso(\.sha256)?/;
+    return undef unless $file && $file =~ 
m/(GNOME_.*|.*(Media|Current|Next))\.iso(\.sha256(\.asc)?)?/;
 
     my $dest;
     for my $root (@roots) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/RootRemote.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/RootRemote.pm
--- old/MirrorCache-1.052/lib/MirrorCache/WebAPI/Plugin/RootRemote.pm   
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/WebAPI/Plugin/RootRemote.pm   
2023-02-09 09:52:35.000000000 +0100
@@ -75,7 +75,7 @@
     } elsif ($deep) {
         my $path1 = $path . '/';
         my $rootlocation = $self->rooturl;
-        my $url = $rootlocation . $path1;
+        my $url = $rootlocation . $path1 . '?realpath';
         my $ua = Mojo::UserAgent->new->max_redirects(0)->request_timeout(1);
         my $tx = $ua->head($url, {'User-Agent' => 
'MirrorCache/detect_redirect'});
         my $res = $tx->res;
@@ -83,6 +83,8 @@
         # redirect on oneself
         if ($res->is_redirect && $res->headers) {
             my $location1 = $res->headers->location;
+            $location1 =~ s/\?realpath=?$//;
+            return substr($location1,0,-1) if '/' eq substr($location1,0,1);
             if ($location1 && $path1 ne substr($location1, -length($path1))) {
                 my $i = rindex($location1, $rootlocation, 0);
                 if ($i ne -1) {
@@ -129,7 +131,7 @@
     my $c = $dm->c;
 
     if ($nfs && $dm->must_render_from_root && -f $nfs . $filepath) {
-        $c->render_file(filepath => $nfs . $filepath, content_type => 
$dm->mime);
+        $c->render_file(filepath => $nfs . $filepath, content_type => 
$dm->mime, content_disposition => 'inline');
         $c->stat->redirect_to_root($dm, $not_miss);
         return 1;
     }
@@ -146,7 +148,7 @@
     my $c = $dm->c;
 
     return undef unless($dm->must_render_from_root && -f $nfs . $filepath);
-    $c->render_file(filepath => $nfs . $filepath, content_type => $dm->mime);
+    $c->render_file(filepath => $nfs . $filepath, content_type => $dm->mime, 
content_disposition => 'inline');
     $c->stat->redirect_to_root($dm, 1);
     return 1;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/lib/MirrorCache/WebAPI.pm 
new/MirrorCache-1.056/lib/MirrorCache/WebAPI.pm
--- old/MirrorCache-1.052/lib/MirrorCache/WebAPI.pm     2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/WebAPI.pm     2023-02-09 
09:52:35.000000000 +0100
@@ -173,6 +173,8 @@
     my $rest = $r->any('/rest');
     my $rest_r    = $rest->any('/')->to(namespace => 
'MirrorCache::WebAPI::Controller::Rest');
     $rest_r->get('/server')->name('rest_server')->to('table#list', table => 
'Server');
+    
$rest_r->get('/server_location')->name('rest_server_location')->to('server_location#list');
+    $rest_r->get('/server/location')                              
->to('server_location#list');
     $rest_r->get('/server/:id')->to('table#list', table => 'Server');
     $rest_r->get('/project')->to('project#list');
     $rest_r->get('/project/:name')->to('project#show');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/resources/migrations/Pg.sql 
new/MirrorCache-1.056/lib/MirrorCache/resources/migrations/Pg.sql
--- old/MirrorCache-1.052/lib/MirrorCache/resources/migrations/Pg.sql   
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/resources/migrations/Pg.sql   
2023-02-09 09:52:35.000000000 +0100
@@ -370,3 +370,5 @@
 );
 -- 28
 -- do nothing
+-- 29
+alter table hash add column if not exists sha512 varchar(128);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/lib/MirrorCache/resources/migrations/mysql.sql 
new/MirrorCache-1.056/lib/MirrorCache/resources/migrations/mysql.sql
--- old/MirrorCache-1.052/lib/MirrorCache/resources/migrations/mysql.sql        
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/lib/MirrorCache/resources/migrations/mysql.sql        
2023-02-09 09:52:35.000000000 +0100
@@ -371,3 +371,5 @@
 update popular_os set version = '\\1' where version = '\1';
 update popular_os set version = '\\2' where version = '\2';
 update popular_os set version = '\\3' where version = '\3';
+-- 29 up
+alter table hash add column if not exists sha512 varchar(128);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/t/environ/01-smoke-mirror-provider.sh 
new/MirrorCache-1.056/t/environ/01-smoke-mirror-provider.sh
--- old/MirrorCache-1.052/t/environ/01-smoke-mirror-provider.sh 1970-01-01 
01:00:00.000000000 +0100
+++ new/MirrorCache-1.056/t/environ/01-smoke-mirror-provider.sh 2023-02-09 
09:52:35.000000000 +0100
@@ -0,0 +1,69 @@
+#!lib/test-in-container-environ.sh
+set -ex
+
+mcmirror=$(environ mc5 $(pwd))
+mcna=$(environ mc1 $(pwd))
+mcnaeast=$(environ mc2 $(pwd))
+
+ap8=$(environ ap8)
+ap7=$(environ ap7)
+
+$mcmirror/gen_env MIRRORCACHE_MODE=mirror_provider
+
+
+$mcmirror/start
+
+$mcmirror/sql "insert into server(hostname,urldir,enabled,country,region) 
select '$($ap7/print_address)','','t','us','na'"
+$mcmirror/sql "insert into server(hostname,urldir,enabled,country,region) 
select '$($ap8/print_address)','','t','us','na'"
+
+$mcmirror/sql "insert into server_capability_declaration(server_id, 
capability, enabled, extra) select '1','region','t','na-east,na-west'"
+
+$mcmirror/curl /rest/server_location?region=na      | grep 
$($ap7/print_address) | grep $($ap8/print_address)
+$mcmirror/curl /rest/server_location?region=na-east | grep 
$($ap7/print_address)
+rc=0
+$mcmirror/curl /rest/server_location?region=na-east | grep 
$($ap8/print_address) || rc=$?
+test $rc -gt 0
+
+$mcna/gen_env 
MIRRORCACHE_MIRROR_PROVIDER=$($mcmirror/print_address)/rest/server_location?region=na
 MIRRORCACHE_MIRROR_PROVIDER_SYNC_RETRY_INTERVAL=1
+$mcna/start
+# the job importing mirrors should schedule automatically because 
mirror_provider_region is defined
+$mcna/backstage/shoot
+
+$mcna/sql_test 2 = 'select count(*) from server' # both servers are imported
+$mcna/curl /rest/server | grep $($ap7/print_address) | grep 
$($ap8/print_address) | grep '\bus\b'
+
+
+$mcnaeast/gen_env MIRRORCACHE_INI=$mcnaeast/conf.ini
+
+(
+echo 
mirror_provider=$($mcmirror/print_address)/rest/server_location?region=na-east
+echo
+echo [db]
+echo
+) >> $mcnaeast/conf.ini
+
+
+$mcnaeast/start
+# the job importing mirrors should schedule automatically because 
mirror_provider_region is defined
+$mcnaeast/backstage/shoot
+
+$mcnaeast/sql_test 1 = 'select count(*) from server' # only one servers are 
imported
+
+rc=0
+$mcnaeast/curl /rest/server | grep $($ap7/print_address) | grep 
'"country":"us"'
+$mcnaeast/curl /rest/server | grep $($ap8/print_address) || rc=$?
+
+test $rc -gt 0
+
+sleep 1
+echo change server on mcmirror, make sure in gets synced
+$mcmirror/sql "update server set country = 'ca' where id = 1";
+$mcna/sql_test us = "select country from server where id = 1"
+$mcna/backstage/shoot
+$mcna/sql_test ca = "select country from server where id = 1"
+
+echo now restart job on mc1, manually check that job is ok
+sleep 1
+$mcna/backstage/shoot
+
+echo success
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/t/environ/02-files-hashes-import.sh 
new/MirrorCache-1.056/t/environ/02-files-hashes-import.sh
--- old/MirrorCache-1.052/t/environ/02-files-hashes-import.sh   2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/t/environ/02-files-hashes-import.sh   2023-02-09 
09:52:35.000000000 +0100
@@ -8,45 +8,48 @@
 # hq mirros: ap1 ap2
 # na mirros: ap3 ap4
 
-for i in 9 6; do
+for i in 6 9; do
     x=$(environ mc$i $(pwd))
-    mkdir -p $x/dt/{folder1,folder2,folder3,folder4}
-    echo $x/dt/{folder1,folder2,folder3,folder4}/{file1.1,file2.1}.dat | xargs 
-n 1 touch
-    echo 1111111111 > $x/dt/folder1/file1.1.dat
-    echo 1111111112 > $x/dt/folder2/file1.1.dat
     eval mc$i=$x
 done
 
 for i in 1 2 3 4; do
     x=$(environ ap$i)
+    $x/start
+    eval ap$i=$x
+done
+
+for x in mc9 ap1 ap2 ap3 ap4; do
     mkdir -p $x/dt/{folder1,folder2,folder3,folder4}
     echo $x/dt/{folder1,folder2,folder3,folder4}/{file1.1,file2.1}.dat | xargs 
-n 1 touch
     echo 1111111111 > $x/dt/folder1/file1.1.dat
     echo 1111111112 > $x/dt/folder2/file1.1.dat
-    eval ap$i=$x
-    $x/start
+    ( cd $x/dt ; ln -s folder1 link1 )
+    mkdir $x/dt/folder1/child1
+    touch $x/dt/folder1/child1/child1.1.dat
 done
 
+
 # set the same modification time for file1.1.dat
-touch -d "$(date -R -r $mc9/dt/folder1/file1.1.dat)" 
{$mc6,$ap1,$ap2,$ap3,$ap4}/dt/folder1/file1.1.dat
+touch -d "$(date -R -r $mc9/dt/folder1/file1.1.dat)" 
{$ap1,$ap2,$ap3,$ap4}/dt/folder1/file1.1.dat
 
 hq_address=$($mc9/print_address)
 na_address=$($mc6/print_address)
 na_interface=127.0.0.2
 
 # deploy db
-$mc9/gen_env MIRRORCACHE_HASHES_COLLECT=1 MIRRORCACHE_HASHES_PIECES_MIN_SIZE=5 
"MIRRORCACHE_TOP_FOLDERS='folder1 folder2 folder3 folder4'" 
MIRRORCACHE_BRANDING=SUSE MIRRORCACHE_WORKERS=4 MIRRORCACHE_DAEMON=1
+$mc9/gen_env MIRRORCACHE_HASHES_COLLECT=1 MIRRORCACHE_HASHES_PIECES_MIN_SIZE=5 
"MIRRORCACHE_TOP_FOLDERS='folder1 folder2 folder3 folder4 link1'" 
MIRRORCACHE_BRANDING=SUSE MIRRORCACHE_WORKERS=4 MIRRORCACHE_DAEMON=1
 $mc9/backstage/shoot
 
-$mc9/sql "insert into subsidiary(hostname,region) select '$na_address','na'"
+$mc9/sql "insert into subsidiary(hostname,region) select '$na_address','eu'"
 $mc9/start
 $mc9/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap1/print_address)','','t','jp','as'"
 $mc9/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap2/print_address)','','t','jp','as'"
 
-$mc6/gen_env MIRRORCACHE_REGION=na MIRRORCACHE_HEADQUARTER=$hq_address 
"MIRRORCACHE_TOP_FOLDERS='folder1 folder2 folder3'" MIRRORCACHE_HASHES_IMPORT=1
+$mc6/gen_env MIRRORCACHE_REGION=na MIRRORCACHE_HEADQUARTER=$hq_address 
"MIRRORCACHE_TOP_FOLDERS='folder1 folder2 folder3 link1'" 
MIRRORCACHE_HASHES_IMPORT=1 MIRRORCACHE_ROOT=http://$($mc9/print_address)
 $mc6/start
-$mc6/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap3/print_address)','','t','us','na'"
-$mc6/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap4/print_address)','','t','ca','na'"
+$mc6/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap3/print_address)','','t','de','eu'"
+$mc6/sql "insert into server(hostname,urldir,enabled,country,region) select 
'$($ap4/print_address)','','t','dk','eu'"
 
 for i in 9 6; do
     mc$i/backstage/job -e folder_sync -a '["/folder1"]'
@@ -58,10 +61,11 @@
 curl -s "http://$na_address/folder1/?hashes&since=2021-01-01"; | grep 
file1.1.dat
 
 for i in 9 6; do
-    test b2c5860a03d2c4f1f049a3b2409b39a8 == $(mc$i/sql 'select md5 from hash 
where file_id=1')
-    test 5179db3d4263c9cb4ecf0edbc653ca460e3678b7 == $(mc$i/sql 'select sha1 
from hash where file_id=1')
-    test 63d19a99ef7db94ddbb1e4a5083062226551cd8197312e3aa0aa7c369ac3e458 == 
$(mc$i/sql 'select sha256 from hash where file_id=1')
-    test 5179db3d4263c9cb4ecf0edbc653ca460e3678b7 == $(mc$i/sql 'select pieces 
from hash where file_id=1')
+    test b2c5860a03d2c4f1f049a3b2409b39a8 == $(mc$i/sql 'select md5 from hash 
where file_id=2')
+    test 5179db3d4263c9cb4ecf0edbc653ca460e3678b7 == $(mc$i/sql 'select sha1 
from hash where file_id=2')
+    test 63d19a99ef7db94ddbb1e4a5083062226551cd8197312e3aa0aa7c369ac3e458 == 
$(mc$i/sql 'select sha256 from hash where file_id=2')
+    test 5179db3d4263c9cb4ecf0edbc653ca460e3678b7 == $(mc$i/sql 'select pieces 
from hash where file_id=2')
+    test 
2a276e680779492af2ed54ba5661ac5f35b39e363c95a55ddfac644c1aca2c3f68333225362e66536460999a7f86b1f2dc7e8ef469e3dc5042ad07d491f13de2
 == $(mc$i/sql 'select sha512 from hash where file_id=2')
 done
 
 mc9/curl -sL /folder1/file1.1.dat.metalink | grep 
63d19a99ef7db94ddbb1e4a5083062226551cd8197312e3aa0aa7c369ac3e458
@@ -81,13 +85,13 @@
 curl -si "http://$hq_address/folder2?hashes";
 mc9/backstage/shoot
 mc9/backstage/shoot -q hashes
-test d8f5889697e9ec5ba9a8ab4aede6e7d1d7858884e81db19b3e9780d6a64671a3 == 
$(mc9/sql 'select sha256 from hash where file_id=3')
+test d8f5889697e9ec5ba9a8ab4aede6e7d1d7858884e81db19b3e9780d6a64671a3 == 
$(mc9/sql 'select sha256 from hash where file_id=4')
 
 mc6/backstage/job -e folder_sync -a '["/folder2"]'
 mc6/backstage/shoot
 mc6/backstage/shoot -q hashes
 
-test d8f5889697e9ec5ba9a8ab4aede6e7d1d7858884e81db19b3e9780d6a64671a3 == 
$(mc6/sql 'select sha256 from hash where file_id=3')
+test d8f5889697e9ec5ba9a8ab4aede6e7d1d7858884e81db19b3e9780d6a64671a3 == 
$(mc6/sql 'select sha256 from hash where file_id=4')
 
 DELAY=1;
 echo Import folder unknown on master, but relay on automatic retry
@@ -97,11 +101,11 @@
 
 mc9/backstage/shoot
 mc9/backstage/shoot -q hashes
-test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=5')
+test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=6')
 
 sleep $DELAY
 mc6/backstage/shoot -q hashes
-test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc6/sql 'select sha256 from hash where file_id=5')
+test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc6/sql 'select sha256 from hash where file_id=6')
 
 
 test -n "$(mc6/sql 'select hash_last_import from folder where id=3')"
@@ -112,26 +116,81 @@
 mc9/backstage/job -e folder_sync -a '["/folder4"]'
 mc9/backstage/shoot
 mc9/backstage/shoot -q hashes
-test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=7')
 test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=8')
+test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=9')
 
-mc9/sql 'delete from hash where file_id=8'
+mc9/sql 'delete from hash where file_id=9'
 
 mc6/backstage/job -e folder_sync -a '["/folder4"]'
 mc6/backstage/shoot
 MIRRORCACHE_HASHES_IMPORT_RETRY_DELAY=$DELAY mc6/backstage/shoot -q hashes
 
-test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=7')
-test                                                                  -z 
"$(mc9/sql 'select sha256 from hash where file_id=8')"
+test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=8')
+test                                                                  -z 
"$(mc9/sql 'select sha256 from hash where file_id=9')"
 echo Recalculate hashes on HQ
 mc9/backstage/job -e folder_hashes_create -a '["/folder4"]'
 mc9/backstage/shoot
 
 sleep $DELAY
 mc6/backstage/shoot -q hashes # this should retry the import because some 
hashes were missing
-test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=7')
-test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc6/sql 'select sha256 from hash where file_id=8')
+test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc9/sql 'select sha256 from hash where file_id=8')
+test e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 == 
$(mc6/sql 'select sha256 from hash where file_id=9')
 
 test -n "$(mc6/sql 'select hash_last_import from folder where id=3')"
 
+echo check how symlink work
+cnt=$(mc6/sql 'select count(*) from file')
+
+mc9/curl -I /link1/file1.1.dat
+mc9/curl -I /link1/child1/child1.1.dat
+mc6/curl -I /link1/file1.1.dat
+mc6/curl -I /link1/child1/child1.1.dat
+
+mc9/backstage/job folder_sync_schedule_from_misses
+mc9/backstage/job folder_sync_schedule
+mc9/backstage/job mirror_scan_schedule
+mc9/backstage/shoot
+mc9/backstage/shoot -q hashes
+
+mc9/curl -I /link1/ | grep '200 OK' # no redirects
+mc9/curl -I /link1/file1.1.dat | grep -E 
"$($ap1/print_address)|$($ap2/print_address)"
+mc9/curl -I /link1/child1/child1.1.dat | grep -E 
"$($ap1/print_address)|$($ap2/print_address)"
+
+mc6/backstage/job folder_sync_schedule_from_misses
+mc6/backstage/job folder_sync_schedule
+mc6/backstage/job mirror_scan_schedule
+mc6/backstage/shoot
+mc6/backstage/shoot -q hashes
+
+echo number of files will increase for 1 because of child1.1.dat
+
+
+mc6/curl -I /link1/ | grep '200 OK' # no redirects
+mc6/curl -I /link1/child1/ | grep '200 OK' # no redirects
+mc6/sql_test $((cnt+1)) == 'select count(*) from file'
+# mc6/sql_test /link1 == 'select pathfrom from redirect'
+
+mc6/sql_test /link1 == "select path from folder where path = '/link1'"
+
+mc6/sql_test 0 -lt "select count(*) from folder_diff join folder on folder_id 
= folder.id where path ='/link1'"
+
+mc6/curl -I /link1/file1.1.dat | grep -E 
"$($ap4/print_address)|$($ap3/print_address)"
+
+mc6/curl /link1/file1.1.dat.meta4 \
+    | grep -C20 $($ap3/print_address)/link1/file1.1.dat \
+    | grep -C20 $($ap3/print_address)/folder1/file1.1.dat \
+    | grep -C20 $($ap4/print_address)/link1/file1.1.dat \
+    | grep      $($ap4/print_address)/folder1/file1.1.dat
+
+
+mc6/sql_test /link1/child1 == "select path from folder where path = 
'/link1/child1'"
+
+mc6/sql_test 0 -lt "select count(*) from folder_diff join folder on folder_id 
= folder.id where path ='/link1/child1'"
+
+mc6/curl -I /link1/child1/child1.1.dat | grep -E 
"$($ap4/print_address)|$($ap3/print_address)"
+
+mc6/curl /link1/child1/child1.1.dat.meta4 \
+    | grep -C20 $($ap3/print_address)/link1/child1/child1.1.dat \
+    | grep -C20 $($ap3/print_address)/folder1/child1/child1.1.dat \
+
 echo success
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/t/environ/02-files-hashes.sh 
new/MirrorCache-1.056/t/environ/02-files-hashes.sh
--- old/MirrorCache-1.052/t/environ/02-files-hashes.sh  2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/t/environ/02-files-hashes.sh  2023-02-09 
09:52:35.000000000 +0100
@@ -26,9 +26,11 @@
 
 $mc/db/sql "select * from file"
 $mc/db/sql "select * from hash"
-test b2c5860a03d2c4f1f049a3b2409b39a8 == $($mc/db/sql 'select md5 from hash 
where file_id=1')
-test 5179db3d4263c9cb4ecf0edbc653ca460e3678b7 == $($mc/db/sql 'select sha1 
from hash where file_id=1')
-test 63d19a99ef7db94ddbb1e4a5083062226551cd8197312e3aa0aa7c369ac3e458 == 
$($mc/db/sql 'select sha256 from hash where file_id=1')
+test b2c5860a03d2c4f1f049a3b2409b39a8 == $($mc/sql 'select md5 from hash where 
file_id=1')
+test 5179db3d4263c9cb4ecf0edbc653ca460e3678b7 == $($mc/sql 'select sha1 from 
hash where file_id=1')
+test 63d19a99ef7db94ddbb1e4a5083062226551cd8197312e3aa0aa7c369ac3e458 == 
$($mc/sql 'select sha256 from hash where file_id=1')
+test 
2a276e680779492af2ed54ba5661ac5f35b39e363c95a55ddfac644c1aca2c3f68333225362e66536460999a7f86b1f2dc7e8ef469e3dc5042ad07d491f13de2
 == $($mc/sql 'select sha512 from hash where file_id=1')
+
 test 5179db3d4263c9cb4ecf0edbc653ca460e3678b7 == $($mc/db/sql 'select pieces 
from hash where file_id=1')
 
 # this value 96ff97ccb1 is also reported by zsyncmake (the last bytes are 
hashes):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/t/environ/03-headquarter-subsidiaries-remote.sh 
new/MirrorCache-1.056/t/environ/03-headquarter-subsidiaries-remote.sh
--- old/MirrorCache-1.052/t/environ/03-headquarter-subsidiaries-remote.sh       
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/t/environ/03-headquarter-subsidiaries-remote.sh       
2023-02-09 09:52:35.000000000 +0100
@@ -2,6 +2,7 @@
 set -ex
 
 # root : ng9
+# a mirror in headquarter : ng8
 
 # mc environ by number:
 # 9 - headquarter
@@ -9,6 +10,7 @@
 # 7 - EU subsidiary
 
 root=$(environ ng9)
+mirror=$(environ ng8)
 
 mkdir -p $root/dt/{folder1,folder2,folder3}
 echo $root/dt/{folder1,folder2,folder3}/{file1.1,file2.1}.dat | xargs -n 1 
touch
@@ -18,13 +20,21 @@
 HUGE_FILE_SIZE=9
 FAKEURL="notexists${RANDOM}.com"
 echo -n 1234 > $root/dt/folder1/repodata/filebig1.1.dat
+echo -n 1234 > $root/dt/folder1/repodata/filebig2.1.dat
 echo -n 123  > $root/dt/folder1/repodata/filesmall1.1.dat
 echo -n 123456789 > $root/dt/folder1/repodata/filehuge1.1.dat
+echo -n 123456789 > $root/dt/folder1/repodata/filehuge2.1.dat
 echo repomdcontent > $root/dt/folder1/repodata/repomd.xml
 touch $root/dt/folder1/repodata/repomd.xml.asc
 
 $root/start
 
+$mirror/start
+cp -r $root/dt/* $mirror/dt/
+rm $mirror/dt/folder1/repodata/filebig1.1.dat
+rm $mirror/dt/folder1/repodata/filehuge1.1.dat
+
+
 mc9=$(environ mc9 $(pwd))
 $mc9/gen_env "MIRRORCACHE_TOP_FOLDERS='folder1 folder2 folder3'" \
     MIRRORCACHE_SCHEDULE_RETRY_INTERVAL=0 \
@@ -39,6 +49,9 @@
 
 $mc9/sql "insert into subsidiary(hostname,region) select 'naaddress.com','na'"
 $mc9/sql "insert into subsidiary(hostname,region) select 'euaddress.net','eu'"
+
+$mc9/sql "insert into server(hostname,urldir,country,region,enabled) select 
'$($mirror/print_address)','','cn','as','t'"
+
 $mc9/start
 
 $mc9/backstage/job -e folder_sync -a '["/folder1/repodata"]'
@@ -71,10 +84,14 @@
 
 echo check huge files are redirected to FAKEURL, but we need to scan folder 
first
 $mc9/curl -I --interface $hq_interface 
/download/folder1/repodata/filehuge1.1.dat | grep "Location: 
http://$FAKEURL/folder1/repodata/filehuge1.1.dat";
-$mc9/curl -I --interface $hq_interface 
/download/folder1/repodata/filebig1.1.dat | grep "Location: " | grep 
$($root/print_address)
+$mc9/curl -I --interface $hq_interface 
/download/folder1/repodata/filebig1.1.dat | grep "Location: " | grep 
$($root/print_address)   # we removed it from mirror
+$mc9/curl -I --interface $hq_interface 
/download/folder1/repodata/filebig2.1.dat | grep "Location: " | grep 
$($mirror/print_address) # this is on mirror
 
 $mc9/curl --interface $hq_interface 
/download/folder1/repodata/filehuge1.1.dat.meta4 | grep 
"http://$FAKEURL/folder1/repodata/filehuge1.1.dat";
-$mc9/curl --interface $hq_interface 
/download/folder1/repodata/filehuge1.1.dat.mirrorlist | grep 
"http://$FAKEURL/folder1/repodata/filehuge1.1.dat";
+$mc9/curl --interface $hq_interface 
/download/folder1/repodata/filehuge1.1.dat.mirrorlist | grep 
"http://$FAKEURL/folder1/repodata/filehuge1.1.dat"; # we removed it from mirror
+
+$mc9/curl -I --interface $hq_interface 
/download/folder1/repodata/filehuge1.1.dat | grep 
"http://$FAKEURL/folder1/repodata/filehuge1.1.dat";         # we removed it from 
mirror
+$mc9/curl -I --interface $hq_interface 
/download/folder1/repodata/filehuge2.1.dat | grep 
$($mirror/print_address)/folder1/repodata/filehuge2.1.dat  # this is on mirror
 
 echo success
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/templates/app/myserver/index.html.ep 
new/MirrorCache-1.056/templates/app/myserver/index.html.ep
--- old/MirrorCache-1.052/templates/app/myserver/index.html.ep  2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/templates/app/myserver/index.html.ep  2023-02-09 
09:52:35.000000000 +0100
@@ -8,6 +8,13 @@
 <div class="row">
     <div class="col-sm-12">
         <h2><%= title %></h2>
+        <div id="regionspanelparent" class="card">
+        <div id="regionspanel" style="display: none">
+            <span style="float: left">Regions</span>
+            <ul id="regionspanelul" style="float: left">
+            </ul>
+        </div>
+        </div>
 
         %= include 'layouts/info'
 
@@ -20,6 +27,7 @@
                     <th class="col_value">Hostname</th>
                     <th class="col_value">Urldir</th>
                     <th class="col_value">Region</th>
+                    <th class="col_value">Extra Regions</th>
                     <th class="col_value">Country</th>
                     <th class="col_value">Comment</th>
                     <th class="col_value">Public Notes</th>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/templates/app/server/index.html.ep 
new/MirrorCache-1.056/templates/app/server/index.html.ep
--- old/MirrorCache-1.052/templates/app/server/index.html.ep    2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/templates/app/server/index.html.ep    2023-02-09 
09:52:35.000000000 +0100
@@ -8,6 +8,13 @@
 <div class="row">
     <div class="col-sm-12">
         <h2><%= title %></h2>
+        <div id="regionspanelparent" class="card">
+        <div id="regionspanel" style="display: none">
+            <span style="float: left">Regions</span>
+            <ul id="regionspanelul" style="float: left">
+            </ul>
+        </div>
+        </div>
 
         %= include 'layouts/info'
 
@@ -20,6 +27,7 @@
                     <th class="col_value">Hostname</th>
                     <th class="col_value">Urldir</th>
                     <th class="col_value">Region</th>
+                    <th class="col_value">Extra Regions</th>
                     <th class="col_value">Country</th>
                     <th class="col_value">Comment</th>
                     <th class="col_value">Public Notes</th>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/templates/branding/openSUSE/footer.html.ep 
new/MirrorCache-1.056/templates/branding/openSUSE/footer.html.ep
--- old/MirrorCache-1.052/templates/branding/openSUSE/footer.html.ep    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/templates/branding/openSUSE/footer.html.ep    
2023-02-09 09:52:35.000000000 +0100
@@ -7,7 +7,7 @@
       <div class="list-inline">
         <a class="list-inline-item" 
href="https://en.opensuse.org/Imprint";>Legal notice</a>
         <a class="list-inline-item" 
href="https://github.com/openSUSE/MirrorCache";>Source code</a>
-        <a class="list-inline-item" 
href="https://bugzilla.opensuse.org/";>Report issue</a>
+        <a class="list-inline-item" 
href="https://github.com/openSUSE/MirrorCache/issues/new";>Report issue</a>
         % if (my $ver = eval '$current_version') {
         <a>MirrorCache <%= $ver %></a>
         % }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/MirrorCache-1.052/templates/branding/openSUSE/header.html.ep 
new/MirrorCache-1.056/templates/branding/openSUSE/header.html.ep
--- old/MirrorCache-1.052/templates/branding/openSUSE/header.html.ep    
2023-01-12 09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/templates/branding/openSUSE/header.html.ep    
2023-02-09 09:52:35.000000000 +0100
@@ -75,7 +75,7 @@
           </li><li>
           %= link_to '15.4 Mirrors'  => url_for('/report/mirrors/154') => 
class => 'dropdown-item'
           </li><li>
-          %= link_to '15.3 Mirrors'  => url_for('/report/mirrors/153') => 
class => 'dropdown-item'
+          %= link_to '15.5 Mirrors'  => url_for('/report/mirrors/155') => 
class => 'dropdown-item'
           </li><li>
           %= link_to 'TW Mirrors'  => url_for('/report/mirrors/tumbleweed') => 
class => 'dropdown-item'
           </li><li>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/MirrorCache-1.052/templates/mirrorlist.html.ep 
new/MirrorCache-1.056/templates/mirrorlist.html.ep
--- old/MirrorCache-1.052/templates/mirrorlist.html.ep  2023-01-12 
09:40:42.000000000 +0100
+++ new/MirrorCache-1.056/templates/mirrorlist.html.ep  2023-02-09 
09:52:35.000000000 +0100
@@ -65,6 +65,9 @@
       % if ($file->{mtime}) {
       <li>Last modified: <%= $file->{hmtime} %> (Unix timestamp: <%= 
$file->{mtime} %>)</li>
       % }
+      % if ($file->{sha512}) {
+      <li>SHA-512 Hash: <%= $file->{sha512} %></li>
+      % }
       % if ($file->{sha256}) {
       <li>SHA-256 Hash: <%= $file->{sha256} %></li>
       % }

++++++ MirrorCache.obsinfo ++++++
--- /var/tmp/diff_new_pack.6eIJvz/_old  2023-02-16 16:57:14.396299481 +0100
+++ /var/tmp/diff_new_pack.6eIJvz/_new  2023-02-16 16:57:14.408299533 +0100
@@ -1,5 +1,5 @@
 name: MirrorCache
-version: 1.052
-mtime: 1673512842
-commit: 4b3bfe9c1345b5228f40fb6ad75626a67ab7aee5
+version: 1.056
+mtime: 1675932755
+commit: 5fa14eb5b8ef788ec3f70055537710294b79982b
 

Reply via email to