Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libzypp for openSUSE:Factory checked 
in at 2025-07-21 19:58:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libzypp (Old)
 and      /work/SRC/openSUSE:Factory/.libzypp.new.8875 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libzypp"

Mon Jul 21 19:58:44 2025 rev:520 rq:1294450 version:17.37.12

Changes:
--------
--- /work/SRC/openSUSE:Factory/libzypp/libzypp.changes  2025-07-15 
16:42:14.259982221 +0200
+++ /work/SRC/openSUSE:Factory/.libzypp.new.8875/libzypp.changes        
2025-07-21 19:58:53.819597973 +0200
@@ -1,0 +2,8 @@
+Thu Jul 17 23:37:54 CEST 2025 - m...@suse.de
+
+- Allow explicit request to probe an added repo's URL
+  (bsc#1246466)
+- Fix tests with -DISABLE_MEDIABACKEND_TESTS=1 (fixes #661)
+- version 17.37.12 (35)
+
+-------------------------------------------------------------------

Old:
----
  libzypp-17.37.11.tar.bz2

New:
----
  libzypp-17.37.12.tar.bz2

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

Other differences:
------------------
++++++ libzypp.spec ++++++
--- /var/tmp/diff_new_pack.Gb0FpC/_old  2025-07-21 19:58:54.559628340 +0200
+++ /var/tmp/diff_new_pack.Gb0FpC/_new  2025-07-21 19:58:54.559628340 +0200
@@ -72,7 +72,7 @@
 %endif
 
 Name:           libzypp
-Version:        17.37.11
+Version:        17.37.12
 Release:        0
 License:        GPL-2.0-or-later
 URL:            https://github.com/openSUSE/libzypp

++++++ libzypp-17.37.11.tar.bz2 -> libzypp-17.37.12.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/CMakeLists.txt 
new/libzypp-17.37.12/CMakeLists.txt
--- old/libzypp-17.37.11/CMakeLists.txt 2025-07-07 17:40:11.000000000 +0200
+++ new/libzypp-17.37.12/CMakeLists.txt 2025-07-18 22:21:29.000000000 +0200
@@ -221,8 +221,6 @@
   check_symbol_exists( xmlCtxtSetErrorHandler "libxml/SAX2.h" 
XMLCTXTSETERRORHANDLER_FOUND )
   IF(${XMLCTXTSETERRORHANDLER_FOUND})
     target_compile_definitions( zypp_general_compiler_flags INTERFACE 
HAVE_LIBXML2_XMLCTXTSETERRORHANDLER )
-  ELSE()
-    message(" WADDAFACGGGG ")
   ENDIF()
   cmake_pop_check_state()
 
@@ -357,7 +355,7 @@
   FIND_PROGRAM( CPPCHECK cppcheck )
   if ( CPPCHECK )
     message( "Enabling cppcheck")
-    set(ZYPP_CXX_CPPCHECK 
${CPPCHECK};–std=c++17;--suppress=rethrowNoCurrentException)
+    set(ZYPP_CXX_CPPCHECK 
${CPPCHECK};--std=c++17;--suppress=rethrowNoCurrentException)
   else ( CPPCHECK )
     message(WARNING "cppcheck not found.")
   endif( CPPCHECK )
@@ -445,9 +443,7 @@
     ADD_EXECUTABLE( ${loop_var}_test ${loop_var}_test.cc )
 
     SET(TEST_REQ_LIBS ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} )
-    IF(NOT DISABLE_MEDIABACKEND_TESTS)
-      LIST( APPEND TEST_REQ_LIBS zypp_test_utils )
-    ENDIF()
+    LIST( APPEND TEST_REQ_LIBS zypp_test_utils )
 
     TARGET_LINK_LIBRARIES( ${loop_var}_test PUBLIC zypp_exe_compiler_flags  )
     TARGET_LINK_LIBRARIES( ${loop_var}_test PUBLIC ${TEST_REQ_LIBS}  )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/VERSION.cmake 
new/libzypp-17.37.12/VERSION.cmake
--- old/libzypp-17.37.11/VERSION.cmake  2025-07-14 12:09:34.000000000 +0200
+++ new/libzypp-17.37.12/VERSION.cmake  2025-07-17 23:46:27.000000000 +0200
@@ -61,8 +61,8 @@
 SET(LIBZYPP_MAJOR "17")
 SET(LIBZYPP_COMPATMINOR "35")
 SET(LIBZYPP_MINOR "37")
-SET(LIBZYPP_PATCH "11")
+SET(LIBZYPP_PATCH "12")
 #
-# LAST RELEASED: 17.37.11 (35)
+# LAST RELEASED: 17.37.12 (35)
 # (The number in parenthesis is LIBZYPP_COMPATMINOR)
 #=======
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/package/libzypp.changes 
new/libzypp-17.37.12/package/libzypp.changes
--- old/libzypp-17.37.11/package/libzypp.changes        2025-07-14 
12:09:34.000000000 +0200
+++ new/libzypp-17.37.12/package/libzypp.changes        2025-07-17 
23:46:27.000000000 +0200
@@ -1,4 +1,12 @@
 -------------------------------------------------------------------
+Thu Jul 17 23:37:54 CEST 2025 - m...@suse.de
+
+- Allow explicit request to probe an added repo's URL
+  (bsc#1246466)
+- Fix tests with -DISABLE_MEDIABACKEND_TESTS=1 (fixes #661)
+- version 17.37.12 (35)
+
+-------------------------------------------------------------------
 Mon Jul 14 12:06:07 CEST 2025 - m...@suse.de
 
 - Add runtime check for a broken rpm-4.18.0 --runpostrans
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/tests/CMakeLists.txt 
new/libzypp-17.37.12/tests/CMakeLists.txt
--- old/libzypp-17.37.11/tests/CMakeLists.txt   2023-07-19 11:53:07.000000000 
+0200
+++ new/libzypp-17.37.12/tests/CMakeLists.txt   2025-07-14 17:50:11.000000000 
+0200
@@ -1,9 +1,7 @@
 
 ADD_DEFINITIONS( -DTESTS_SRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}" 
-DTESTS_BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}" )
 
-IF( NOT DISABLE_MEDIABACKEND_TESTS )
 ADD_SUBDIRECTORY(lib)
-ENDIF()
 
 ENABLE_TESTING()
 INCLUDE_DIRECTORIES( ${LIBZYPP_SOURCE_DIR}/tests/lib )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/tests/lib/CMakeLists.txt 
new/libzypp-17.37.12/tests/lib/CMakeLists.txt
--- old/libzypp-17.37.11/tests/lib/CMakeLists.txt       2025-07-08 
11:38:22.000000000 +0200
+++ new/libzypp-17.37.12/tests/lib/CMakeLists.txt       2025-07-14 
17:50:11.000000000 +0200
@@ -1,70 +1,82 @@
-find_program( NGINX nginx )
-find_program( VSFTPD vsftpd )
-find_program( SQUIDPROXY squid )
-find_program( SQUIDPROXY_AUTH basic_ncsa_auth HINTS ${CMAKE_INSTALL_BINDIR} 
${CMAKE_INSTALL_SBINDIR} ${CMAKE_INSTALL_LIBEXECDIR} "/usr/libexec" "/usr/lib" 
PATH_SUFFIXES squid)
-find_library( LIBFCGI NAMES fcgi )
-find_library( LIBFCGI++ NAMES fcgi++ )
-
-if ( NOT NGINX )
-  message( FATAL_ERROR "nginx not found" )
-else()
-  message ( "Using nginx binary at: ${NGINX}" )
-  ADD_DEFINITIONS( -DWEBSRV_BINARY="${NGINX}" )
-endif()
-
-if ( NOT VSFTPD )
-  message( FATAL_ERROR "vsftpd not found" )
-else()
-  message ( "Using vsftpd binary at: ${VSFTPD}" )
-  ADD_DEFINITIONS( -DFTPSRV_BINARY="${VSFTPD}" )
-endif()
-
-if ( NOT SQUIDPROXY )
-  message( FATAL_ERROR "squid not found" )
-else()
-  message ( "Using squid binary at: ${SQUIDPROXY}" )
-  ADD_DEFINITIONS( -DPROXYSRV_BINARY="${SQUIDPROXY}" )
-endif()
-
-if ( NOT SQUIDPROXY_AUTH )
-  message( FATAL_ERROR "basic_ncsa_auth not found" )
-else()
-  message ( "Using basic_ncsa_auth binary at: ${SQUIDPROXY_AUTH}" )
-  ADD_DEFINITIONS( -DPROXYAUTH_BINARY="${SQUIDPROXY_AUTH}" )
-endif()
+add_definitions( -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
 
-if ( NOT LIBFCGI )
-  message( FATAL_ERROR "libfcgi not found" )
-else()
-  message ( "Using libfcgi library at: ${LIBFCGI}" )
-endif()
+if( NOT DISABLE_MEDIABACKEND_TESTS )
+  find_program( NGINX nginx )
+  find_program( VSFTPD vsftpd )
+  find_program( SQUIDPROXY squid )
+  find_program( SQUIDPROXY_AUTH basic_ncsa_auth HINTS ${CMAKE_INSTALL_BINDIR} 
${CMAKE_INSTALL_SBINDIR} ${CMAKE_INSTALL_LIBEXECDIR} "/usr/libexec" "/usr/lib" 
PATH_SUFFIXES squid)
+  find_library( LIBFCGI NAMES fcgi )
+  find_library( LIBFCGI++ NAMES fcgi++ )
+
+  if ( NOT NGINX )
+    message( FATAL_ERROR "nginx not found" )
+  else()
+    message ( "Using nginx binary at: ${NGINX}" )
+    ADD_DEFINITIONS( -DWEBSRV_BINARY="${NGINX}" )
+  endif()
+
+  if ( NOT VSFTPD )
+    message( FATAL_ERROR "vsftpd not found" )
+  else()
+    message ( "Using vsftpd binary at: ${VSFTPD}" )
+    ADD_DEFINITIONS( -DFTPSRV_BINARY="${VSFTPD}" )
+  endif()
+
+  if ( NOT SQUIDPROXY )
+    message( FATAL_ERROR "squid not found" )
+  else()
+    message ( "Using squid binary at: ${SQUIDPROXY}" )
+    ADD_DEFINITIONS( -DPROXYSRV_BINARY="${SQUIDPROXY}" )
+  endif()
+
+  if ( NOT SQUIDPROXY_AUTH )
+    message( FATAL_ERROR "basic_ncsa_auth not found" )
+  else()
+    message ( "Using basic_ncsa_auth binary at: ${SQUIDPROXY_AUTH}" )
+    ADD_DEFINITIONS( -DPROXYAUTH_BINARY="${SQUIDPROXY_AUTH}" )
+  endif()
+
+  if ( NOT LIBFCGI )
+    message( FATAL_ERROR "libfcgi not found" )
+  else()
+    message ( "Using libfcgi library at: ${LIBFCGI}" )
+  endif()
+
+  if ( NOT LIBFCGI++ )
+    message( FATAL_ERROR "libfcgi++ not found" )
+  else()
+    message ( "Using libfcgi++ library at: ${LIBFCGI++}" )
+  endif()
+
+  set( MEDIA_SOURCES
+    FtpServer.h
+    FtpServer.cc
+    ProxyServer.h
+    ProxyServer.cc
+    WebServer.h
+    WebServer.cc
+  )
 
-if ( NOT LIBFCGI++ )
-  message( FATAL_ERROR "libfcgi++ not found" )
-else()
-  message ( "Using libfcgi++ library at: ${LIBFCGI++}" )
 endif()
 
-add_definitions( -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
-
 ADD_LIBRARY(zypp_test_utils STATIC
- FtpServer.h
- FtpServer.cc
- ProxyServer.h
- ProxyServer.cc
  TestSetup.h
  TestTools.h
  TestTools.cc
- WebServer.h
- WebServer.cc
+ ${MEDIA_SOURCES}
 )
 
-# These headers are in different subdirectories depending on the
-# distribution
-CHECK_INCLUDE_FILE( fastcgi/fcgiapp.h FASTCGI_HEADER_DIR )
-IF ( FASTCGI_HEADER_DIR )
-  target_compile_definitions( zypp_test_utils PRIVATE FCGI_IN_SUBDIR=1)
-ENDIF ( FASTCGI_HEADER_DIR )
-
 target_link_libraries( zypp_test_utils PRIVATE zypp_lib_compiler_flags )
-TARGET_LINK_LIBRARIES( zypp_test_utils PUBLIC ${LIBFCGI} ${LIBFCGI++} pthread )
+
+if( NOT DISABLE_MEDIABACKEND_TESTS )
+
+  # These headers are in different subdirectories depending on the
+  # distribution
+  CHECK_INCLUDE_FILE( fastcgi/fcgiapp.h FASTCGI_HEADER_DIR )
+  IF ( FASTCGI_HEADER_DIR )
+    target_compile_definitions( zypp_test_utils PRIVATE FCGI_IN_SUBDIR=1)
+  ENDIF ( FASTCGI_HEADER_DIR )
+
+  TARGET_LINK_LIBRARIES( zypp_test_utils PUBLIC ${LIBFCGI} ${LIBFCGI++} 
pthread )
+endif()
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/tests/media/MediaCurl_test.cc 
new/libzypp-17.37.12/tests/media/MediaCurl_test.cc
--- old/libzypp-17.37.11/tests/media/MediaCurl_test.cc  2025-07-07 
17:40:11.000000000 +0200
+++ new/libzypp-17.37.12/tests/media/MediaCurl_test.cc  2025-07-18 
22:21:30.000000000 +0200
@@ -78,6 +78,55 @@
     BOOST_REQUIRE_EQUAL( primaryRequests, 1 );
 }
 
+BOOST_DATA_TEST_CASE( base_provide_zck_no_hdrsize, bdata::make( withSSL ) * 
bdata::make( backend ), withSSL, backend )
+{
+
+  int primaryRequests = 0;
+
+  zypp::Pathname testRoot = 
zypp::Pathname(TESTS_SRC_DIR)/"zyppng/data/downloader";
+  WebServer web( testRoot.c_str(), 10001, withSSL );
+  BOOST_REQUIRE( web.start() );
+
+  web.addRequestHandler("primary", [ & ]( WebServer::Request &req ){
+    primaryRequests++;
+    req.rout << "Location: /primary.xml.zck\r\n\r\n";
+    return;
+  });
+
+  zypp::media::MediaManager   mm;
+  zypp::media::MediaAccessId  id;
+
+  zypp::Url mediaUrl = web.url();
+  mediaUrl.setQueryParam( "mediahandler", backend );
+
+  if( withSSL ) {
+    mediaUrl.setQueryParam("ssl_capath", web.caPath().asString() );
+  }
+
+  BOOST_CHECK_NO_THROW( id = mm.open( mediaUrl ) );
+  BOOST_CHECK_NO_THROW( mm.attach(id) );
+  zypp_defer {
+    mm.releaseAll ();
+    mm.close (id);
+  };
+
+  zypp::OnMediaLocation loc("/handler/primary");
+  loc.setDeltafile( testRoot/"primary-deltatemplate.xml.zck" );
+  loc.setDownloadSize( makeBytes(274638) );
+  loc.setHeaderChecksum( zypp::CheckSum( zypp::Digest::sha256(), 
"90a1a1b99ba3b6c8ae9f14b0c8b8c43141c69ec3388bfa3b9915fbeea03926b7") );
+
+  BOOST_CHECK_NO_THROW( mm.provideFile( id, loc ) );
+
+  // if zck is enabled, we have 2 requests, otherwise its just a normal provide
+#ifdef ENABLE_ZCHUNK_COMPRESSION
+  if ( backend == "curl2" )
+    BOOST_REQUIRE_EQUAL( primaryRequests, 3 ); // lead + header + chunks
+  else
+#endif
+    BOOST_REQUIRE_EQUAL( primaryRequests, 1 );
+}
+
+
 // case request with filesize not matching
 BOOST_DATA_TEST_CASE( base_provide_wrong_filesize, bdata::make( withSSL ) * 
bdata::make( backend ), withSSL, backend )
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libzypp-17.37.11/tools/zypp-media-http/downloader/downloader.cc 
new/libzypp-17.37.12/tools/zypp-media-http/downloader/downloader.cc
--- old/libzypp-17.37.11/tools/zypp-media-http/downloader/downloader.cc 
2025-02-24 14:59:49.000000000 +0100
+++ new/libzypp-17.37.12/tools/zypp-media-http/downloader/downloader.cc 
2025-07-18 22:21:30.000000000 +0200
@@ -101,7 +101,7 @@
   bool DownloadPrivateBase::hasZckInfo() const
   {
     if ( zypp::indeterminate(_specHasZckInfo) )
-      _specHasZckInfo = ( _spec.headerSize() > 0 && ZckHelper::isZchunkFile( 
_spec.deltaFile() ) );
+      _specHasZckInfo = ( _spec.headerSize() > 0 && ZckLoader::isZchunkFile( 
_spec.deltaFile() ) );
     return bool(_specHasZckInfo);
   }
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libzypp-17.37.11/tools/zypp-media-http/downloader/private/downloaderstates/initial_p.cc
 
new/libzypp-17.37.12/tools/zypp-media-http/downloader/private/downloaderstates/initial_p.cc
--- 
old/libzypp-17.37.11/tools/zypp-media-http/downloader/private/downloaderstates/initial_p.cc
 2025-02-24 14:59:49.000000000 +0100
+++ 
new/libzypp-17.37.12/tools/zypp-media-http/downloader/private/downloaderstates/initial_p.cc
 2025-07-18 22:21:30.000000000 +0200
@@ -33,7 +33,7 @@
     }
 
 #if ENABLE_ZCHUNK_COMPRESSION
-    bool deltaZck = ZckHelper::isZchunkFile( spec.deltaFile() );
+    bool deltaZck = ZckLoader::isZchunkFile( spec.deltaFile() );
 #endif
     if ( spec.metalinkEnabled() ) {
 #if ENABLE_ZCHUNK_COMPRESSION
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libzypp-17.37.11/tools/zypp-media-http/downloader/private/downloaderstates/preparemulti_p.cc
 
new/libzypp-17.37.12/tools/zypp-media-http/downloader/private/downloaderstates/preparemulti_p.cc
--- 
old/libzypp-17.37.11/tools/zypp-media-http/downloader/private/downloaderstates/preparemulti_p.cc
    2025-02-24 14:59:49.000000000 +0100
+++ 
new/libzypp-17.37.12/tools/zypp-media-http/downloader/private/downloaderstates/preparemulti_p.cc
    2025-07-18 22:21:30.000000000 +0200
@@ -39,7 +39,7 @@
     const auto &url = spec.url();
     const auto &targetPath = spec.targetPath();
 #if ENABLE_ZCHUNK_COMPRESSION
-    _haveZckData = (ZckHelper::isZchunkFile( spec.deltaFile() )  && 
spec.headerSize() > 0);
+    _haveZckData = (ZckLoader::isZchunkFile( spec.deltaFile() )  && 
spec.headerSize() > 0);
     MIL << " Upgrading request for URL: "<< url << " to multipart download , 
which zckunk=" << _haveZckData << std::endl;
 #else
     MIL << " Upgrading request for URL: "<< url << " to multipart download , 
which zckunk=false" << std::endl;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libzypp-17.37.11/tools/zypp-media-http/downloader/private/downloaderstates/zck_p.cc
 
new/libzypp-17.37.12/tools/zypp-media-http/downloader/private/downloaderstates/zck_p.cc
--- 
old/libzypp-17.37.11/tools/zypp-media-http/downloader/private/downloaderstates/zck_p.cc
     2025-02-24 14:59:49.000000000 +0100
+++ 
new/libzypp-17.37.12/tools/zypp-media-http/downloader/private/downloaderstates/zck_p.cc
     2025-07-18 22:21:30.000000000 +0200
@@ -71,7 +71,7 @@
 
   void DLZckHeadState::gotFinished()
   {
-    if ( ZckHelper::isZchunkFile( stateMachine()._spec.targetPath() ) )
+    if ( ZckLoader::isZchunkFile( stateMachine()._spec.targetPath() ) )
       return BasicDownloaderStateBase::gotFinished();
     failed ( "Downloaded header is not a zchunk header");
   }
@@ -101,21 +101,21 @@
     // @TODO get this from zchunk file?
     _fileSize = spec.expectedFileSize();
 
-    auto prepareRes = ZckHelper::prepareZck ( spec.deltaFile (), 
spec.targetPath (), _fileSize );
+    auto prepareRes = ZckLoader::prepareZck ( spec.deltaFile (), 
spec.targetPath (), _fileSize );
     switch( prepareRes._code ) {
-      case ZckHelper::PrepareResult::Error: {
+      case ZckLoader::PrepareResult::Error: {
         return setFailed ( std::move(prepareRes._message) );
       }
-      case ZckHelper::PrepareResult::ExceedsMaxLen: {
+      case ZckLoader::PrepareResult::ExceedsMaxLen: {
         return setFailed( NetworkRequestErrorPrivate::customError(
                             NetworkRequestError::ExceededMaxLen,
                             std::move(prepareRes._message) )
                           );
       }
-      case ZckHelper::PrepareResult::NothingToDo: {
+      case ZckLoader::PrepareResult::NothingToDo: {
         return setFinished();
       }
-      case ZckHelper::PrepareResult::Success:
+      case ZckLoader::PrepareResult::Success:
         // handle down below
         break;
     }
@@ -137,7 +137,7 @@
       _preferredChunkSize = sm._spec.preferredChunkSize();
     }
 
-    std::for_each( prepareRes._blocks.begin (), prepareRes._blocks.end(), [&]( 
const ZckHelper::Block &block ) {
+    std::for_each( prepareRes._blocks.begin (), prepareRes._blocks.end(), [&]( 
const ZckLoader::Block &block ) {
       _ranges.push_back ( Block{ block } );
     });
 
@@ -160,7 +160,7 @@
     const auto &spec = stateMachine()._spec;
 
     std::string err;
-    if ( !ZckHelper::validateZckFile ( spec.targetPath(), err ) ) {
+    if ( !ZckLoader::validateZckFile ( spec.targetPath(), err ) ) {
       return setFailed ( std::move(err) );
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp/RepoManager.cc 
new/libzypp-17.37.12/zypp/RepoManager.cc
--- old/libzypp-17.37.11/zypp/RepoManager.cc    2025-07-04 16:20:12.000000000 
+0200
+++ new/libzypp-17.37.12/zypp/RepoManager.cc    2025-07-17 19:50:16.000000000 
+0200
@@ -178,11 +178,11 @@
   repo::RepoType RepoManager::probe( const Url & url ) const
   { return _pimpl->ngMgr().probe( {url} ).unwrap(); }
 
-  void RepoManager::addRepository( const RepoInfo &info, const 
ProgressData::ReceiverFnc & progressrcv )
+  void RepoManager::addRepository( const RepoInfo &info, const TriBool & 
forcedProbe, const ProgressData::ReceiverFnc & progressrcv )
   {
     callback::SendReport<ProgressReport> report;
     auto adapt = zyppng::ProgressObserverAdaptor( progressrcv, report );
-    RepoInfo updatedRepo = _pimpl->ngMgr().addRepository( info, 
adapt.observer() ).unwrap();
+    RepoInfo updatedRepo = _pimpl->ngMgr().addRepository( info, 
adapt.observer(), forcedProbe ).unwrap();
 
     // We should fix the API as we must inject those paths
     // into the repoinfo in order to keep it usable.
@@ -192,6 +192,9 @@
     oinfo.setPackagesPath( zyppng::packagescache_path_for_repoinfo( 
_pimpl->ngMgr().options(), updatedRepo ).unwrap() );
   }
 
+  void RepoManager::addRepository( const RepoInfo &info, const 
ProgressData::ReceiverFnc & progressrcv )
+  { addRepository( info, indeterminate, progressrcv ); }
+
   void RepoManager::addRepositories( const Url &url, const 
ProgressData::ReceiverFnc & progressrcv )
   { return _pimpl->ngMgr().addRepositories( url, nullptr ).unwrap(); }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp/RepoManager.h 
new/libzypp-17.37.12/zypp/RepoManager.h
--- old/libzypp-17.37.11/zypp/RepoManager.h     2025-06-18 11:57:31.000000000 
+0200
+++ new/libzypp-17.37.12/zypp/RepoManager.h     2025-07-17 19:50:16.000000000 
+0200
@@ -31,6 +31,7 @@
 #include <zypp/RepoManagerOptions.h>
 #include <utility>
 #include <zypp-core/ui/ProgressData>
+#include <zypp-core/TriBool.h>
 
 ///////////////////////////////////////////////////////////////////
 namespace zypp
@@ -380,7 +381,9 @@
     */
    void addRepository( const RepoInfo &info,
                        const ProgressData::ReceiverFnc & progressrcv = 
ProgressData::ReceiverFnc() );
-
+   /** \overload Explicitly request probing or no probing. */
+   void addRepository( const RepoInfo &info, const TriBool & forcedProbe,
+                       const ProgressData::ReceiverFnc & progressrcv = 
ProgressData::ReceiverFnc() );
    /**
     * \short Adds repositores from a repo file to the list of known 
repositories.
     * \param url Url of the repo file. The URL is subject to repo variable 
expansion.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp/media/MediaCurl2.cc 
new/libzypp-17.37.12/zypp/media/MediaCurl2.cc
--- old/libzypp-17.37.11/zypp/media/MediaCurl2.cc       2025-06-18 
11:57:31.000000000 +0200
+++ new/libzypp-17.37.12/zypp/media/MediaCurl2.cc       2025-07-18 
22:21:30.000000000 +0200
@@ -342,65 +342,60 @@
 
       // HERE add zchunk logic if required
       if ( !srcFile.deltafile().empty()
-           && zyppng::ZckHelper::isZchunkFile (srcFile.deltafile ())
-           && srcFile.headerSize () > 0 ) {
+           && zyppng::ZckLoader::isZchunkFile (srcFile.deltafile ()) ) {
 
-        // first fetch the zck header
-        std::optional<zypp::Digest> digest;
-        UByteArray sum;
-
-        const auto &headerSum = srcFile.headerChecksum();
-        if ( !headerSum.empty () ) {
-          digest = zypp::Digest();
-          if ( !digest->create( headerSum.type() ) ) {
-            ERR << "Unknown header checksum type " << headerSum.type() << 
std::endl;
-            return false;
-          }
-          sum = zypp::Digest::hexStringToUByteArray( headerSum.checksum() );
-        }
+        zyppng::Ref<zyppng::ZckLoader> zckHelper = 
std::make_shared<zyppng::ZckLoader>();
 
-        reqData._req->addRequestRange( 0, srcFile.headerSize(), 
std::move(digest), sum );
-        executeRequest ( reqData, nullptr );
+        const auto &fetchChunks = [&]( const 
std::vector<zyppng::ZckLoader::Block> &blocks ){
 
-        reqData._req->resetRequestRanges();
-
-        auto res = zyppng::ZckHelper::prepareZck( srcFile.deltafile(), target, 
srcFile.downloadSize() );
-        switch(res._code) {
-          case zyppng::ZckHelper::PrepareResult::Error: {
-            ERR << "Failed to setup zchunk because of: " << res._message << 
std::endl;
-            return false;
-          }
-          case zyppng::ZckHelper::PrepareResult::NothingToDo:
-            return true; // already done
-          case zyppng::ZckHelper::PrepareResult::ExceedsMaxLen:
-            ZYPP_THROW( MediaFileSizeExceededException( reqData._req->url(), 
srcFile.downloadSize(), res._message ));
-          case zyppng::ZckHelper::PrepareResult::Success:
-            break;
-        }
+          reqData._req->resetRequestRanges();
 
-        for ( const auto &block : res._blocks ) {
-          if ( block._checksum.size() && block._chksumtype.size() ) {
-            std::optional<zypp::Digest> dig = zypp::Digest();
-            if ( !dig->create( block._chksumtype ) ) {
-              WAR_MEDIA << "Trying to create Digest with chksum type " << 
block._chksumtype << " failed " << std::endl;
-              return false;
+          for ( const auto &block : blocks ) {
+            if ( block._checksum.size() && block._chksumtype.size() ) {
+              std::optional<zypp::Digest> dig = zypp::Digest();
+              if ( !dig->create( block._chksumtype ) ) {
+                WAR_MEDIA << "Trying to create Digest with chksum type " << 
block._chksumtype << " failed " << std::endl;
+                zckHelper->setFailed( str::Str() << "Trying to create Digest 
with chksum type " << block._chksumtype << " failed " );
+                return;
+              }
+
+              if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 )
+                DBG_MEDIA << "Starting block " << block._start << " with 
checksum " << zypp::Digest::digestVectorToString( block._checksum ) << "." << 
std::endl;
+              reqData._req->addRequestRange( block._start, block._len, 
std::move(dig), block._checksum, {}, block._relevantDigestLen, block._chksumPad 
);
+            } else {
+              if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 )
+                DBG_MEDIA << "Starting block " << block._start << " without 
checksum!" << std::endl;
+              reqData._req->addRequestRange( block._start, block._len );
             }
+          };
 
-            if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 )
-              DBG_MEDIA << "Starting block " << block._start << " with 
checksum " << zypp::Digest::digestVectorToString( block._checksum ) << "." << 
std::endl;
-            reqData._req->addRequestRange( block._start, block._len, 
std::move(dig), block._checksum, {}, block._relevantDigestLen, block._chksumPad 
);
-          }
+          executeRequest ( reqData, &report );
+          zckHelper->cont().unwrap();
         };
 
-        executeRequest ( reqData, &report );
 
-        //we might have the file ready
-        std::string err;
-        if ( !zyppng::ZckHelper::validateZckFile( target, err) ) {
-          ERR << "ZCK failed with error: " << err << std::endl;
-          return false;
+        zyppng::ZckLoader::PrepareResult res;
+        const auto &fin = [&]( zyppng::ZckLoader::PrepareResult result ){
+          res = std::move(result);
+        };
+
+        const auto &hdrSize = srcFile.headerSize();
+        const auto &dSize = srcFile.downloadSize();
+        zckHelper->connectFunc( &zyppng::ZckLoader::sigBlocksRequired, 
fetchChunks );
+        zckHelper->connectFunc( &zyppng::ZckLoader::sigFinished, fin );
+        zckHelper->buildZchunkFile( target, srcFile.deltafile(), dSize ? dSize 
: std::optional<zypp::ByteCount>{}, hdrSize ? hdrSize : 
std::optional<zypp::ByteCount>{} ).unwrap();
+
+        switch(res._code) {
+          case zyppng::ZckLoader::PrepareResult::Error: {
+            ERR << "Failed to setup zchunk because of: " << res._message << 
std::endl;
+            return false;
+          }
+          case zyppng::ZckLoader::PrepareResult::ExceedsMaxLen:
+            ZYPP_THROW( MediaFileSizeExceededException( reqData._req->url(), 
srcFile.downloadSize(), res._message ));
+          case zyppng::ZckLoader::PrepareResult::Success:
+          case zyppng::ZckLoader::PrepareResult::NothingToDo:
+            return true; //done
         }
-        return true;
       }
 #endif
       return false;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp/misc/YamlTestcaseHelpers.h 
new/libzypp-17.37.12/zypp/misc/YamlTestcaseHelpers.h
--- old/libzypp-17.37.11/zypp/misc/YamlTestcaseHelpers.h        2025-01-09 
16:00:09.000000000 +0100
+++ new/libzypp-17.37.12/zypp/misc/YamlTestcaseHelpers.h        2025-07-18 
22:21:30.000000000 +0200
@@ -29,7 +29,7 @@
     for ( YAML::const_iterator it = setup.begin(); it != setup.end(); it++ ) {
 
       const std::string &key = it->first.as<std::string>();
-      const auto &data = it->second;
+      const auto &data = (*it).second;
 
       MIL << "Found key " << key << std::endl;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libzypp-17.37.11/zypp/ng/repo/workflows/repomanagerwf.cc 
new/libzypp-17.37.12/zypp/ng/repo/workflows/repomanagerwf.cc
--- old/libzypp-17.37.11/zypp/ng/repo/workflows/repomanagerwf.cc        
2025-06-18 11:57:31.000000000 +0200
+++ new/libzypp-17.37.12/zypp/ng/repo/workflows/repomanagerwf.cc        
2025-07-17 19:50:16.000000000 +0200
@@ -888,8 +888,9 @@
 
       ZYPP_ENABLE_LOGIC_BASE(Executor, OpType);
 
-      AddRepoLogic( RepoManagerPtrType &&repoMgrRef, RepoInfo &&info, 
ProgressObserverRef &&myProgress )
+      AddRepoLogic( RepoManagerPtrType &&repoMgrRef, RepoInfo &&info, 
ProgressObserverRef &&myProgress, const zypp::TriBool & forcedProbe )
         : _repoMgrRef( std::move(repoMgrRef) )
+        , _doProbeUrl( zypp::indeterminate(forcedProbe) ? 
_repoMgrRef->options().probe : bool(forcedProbe) )
         , _info( std::move(info) )
         , _myProgress ( std::move(myProgress) )
       {}
@@ -908,7 +909,7 @@
             return makeReadyResult( expected<RepoInfo>::error( 
ZYPP_EXCPT_PTR(zypp::repo::RepoAlreadyExistsException(_info)) ) );
 
           // check the first url for now
-          if ( _repoMgrRef->options().probe )
+          if ( _doProbeUrl )
           {
             DBG << "unknown repository type, probing" << std::endl;
             return assert_urls(_info)
@@ -941,19 +942,20 @@
       }
 
       RepoManagerPtrType _repoMgrRef;
+      bool _doProbeUrl;  ///< RepoManagerOptions::probe opt. overwritten in by 
ctor arg \a forcedProbe
       RepoInfo _info;
       ProgressObserverRef _myProgress;
     };
   };
 
-  AsyncOpRef<expected<RepoInfo> > addRepository( AsyncRepoManagerRef mgr, 
RepoInfo info, ProgressObserverRef myProgress )
+  AsyncOpRef<expected<RepoInfo> > addRepository( AsyncRepoManagerRef mgr, 
RepoInfo info, ProgressObserverRef myProgress, const zypp::TriBool & 
forcedProbe )
   {
-    return SimpleExecutor<AddRepoLogic, AsyncOp<expected<RepoInfo>>>::run( 
std::move(mgr), std::move(info), std::move(myProgress) );
+    return SimpleExecutor<AddRepoLogic, AsyncOp<expected<RepoInfo>>>::run( 
std::move(mgr), std::move(info), std::move(myProgress), forcedProbe );
   }
 
-  expected<RepoInfo> addRepository( SyncRepoManagerRef mgr, const RepoInfo 
&info, ProgressObserverRef myProgress )
+  expected<RepoInfo> addRepository( SyncRepoManagerRef mgr, const RepoInfo 
&info, ProgressObserverRef myProgress, const zypp::TriBool & forcedProbe )
   {
-    return SimpleExecutor<AddRepoLogic, SyncOp<expected<RepoInfo>>>::run( 
std::move(mgr), RepoInfo(info), std::move(myProgress) );
+    return SimpleExecutor<AddRepoLogic, SyncOp<expected<RepoInfo>>>::run( 
std::move(mgr), RepoInfo(info), std::move(myProgress), forcedProbe );
   }
 
   namespace {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libzypp-17.37.11/zypp/ng/repo/workflows/repomanagerwf.h 
new/libzypp-17.37.12/zypp/ng/repo/workflows/repomanagerwf.h
--- old/libzypp-17.37.11/zypp/ng/repo/workflows/repomanagerwf.h 2025-06-18 
11:57:31.000000000 +0200
+++ new/libzypp-17.37.12/zypp/ng/repo/workflows/repomanagerwf.h 2025-07-17 
19:50:16.000000000 +0200
@@ -56,8 +56,8 @@
     AsyncOpRef<expected<repo::AsyncRefreshContextRef> > buildCache( 
repo::AsyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy 
policy, ProgressObserverRef progressObserver = nullptr );
     expected<repo::SyncRefreshContextRef> buildCache( 
repo::SyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy 
policy, ProgressObserverRef progressObserver = nullptr );
 
-    AsyncOpRef<expected<RepoInfo>> addRepository( AsyncRepoManagerRef mgr, 
RepoInfo info, ProgressObserverRef myProgress = nullptr );
-    expected<RepoInfo> addRepository( SyncRepoManagerRef mgr, const RepoInfo 
&info, ProgressObserverRef myProgress = nullptr );
+    AsyncOpRef<expected<RepoInfo>> addRepository( AsyncRepoManagerRef mgr, 
RepoInfo info, ProgressObserverRef myProgress = nullptr, const zypp::TriBool & 
forcedProbe = zypp::indeterminate );
+    expected<RepoInfo> addRepository( SyncRepoManagerRef mgr, const RepoInfo 
&info, ProgressObserverRef myProgress = nullptr, const zypp::TriBool & 
forcedProbe = zypp::indeterminate );
 
     AsyncOpRef<expected<void>> addRepositories( AsyncRepoManagerRef mgr, 
zypp::Url url, ProgressObserverRef myProgress = nullptr );
     expected<void> addRepositories( SyncRepoManagerRef mgr, zypp::Url url, 
ProgressObserverRef myProgress = nullptr );
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp/ng/repomanager.cc 
new/libzypp-17.37.12/zypp/ng/repomanager.cc
--- old/libzypp-17.37.11/zypp/ng/repomanager.cc 2025-06-18 11:57:31.000000000 
+0200
+++ new/libzypp-17.37.12/zypp/ng/repomanager.cc 2025-07-17 19:50:16.000000000 
+0200
@@ -991,9 +991,9 @@
   }
 
   template<typename ZyppContextRefType>
-  expected<RepoInfo> RepoManager<ZyppContextRefType>::addRepository(const 
RepoInfo &info, ProgressObserverRef myProgress)
+  expected<RepoInfo> RepoManager<ZyppContextRefType>::addRepository(const 
RepoInfo &info, ProgressObserverRef myProgress, const zypp::TriBool & 
forcedProbe )
   {
-    return joinPipeline( _zyppContext, RepoManagerWorkflow::addRepository( 
shared_this<RepoManager<ZyppContextRefType>>(), info, std::move(myProgress) ) );
+    return joinPipeline( _zyppContext, RepoManagerWorkflow::addRepository( 
shared_this<RepoManager<ZyppContextRefType>>(), info, std::move(myProgress), 
forcedProbe ) );
   }
 
   template<typename ZyppContextRefType>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp/ng/repomanager.h 
new/libzypp-17.37.12/zypp/ng/repomanager.h
--- old/libzypp-17.37.11/zypp/ng/repomanager.h  2025-06-18 11:57:31.000000000 
+0200
+++ new/libzypp-17.37.12/zypp/ng/repomanager.h  2025-07-17 19:50:16.000000000 
+0200
@@ -13,6 +13,7 @@
 #define ZYPP_NG_REPOMANAGER_INCLUDED
 
 #include <utility>
+#include <optional>
 
 #include <zypp/RepoManagerFlags.h>
 #include <zypp/RepoManagerOptions.h>
@@ -39,7 +40,6 @@
   using ServiceInfo         = zypp::ServiceInfo;
   using RepoManagerOptions  = zypp::RepoManagerOptions;
   using PluginRepoverification = zypp_private::repo::PluginRepoverification;
-
   ZYPP_FWD_DECL_TYPE_WITH_REFS( Context );
   ZYPP_FWD_DECL_TYPE_WITH_REFS( SyncContext );
   ZYPP_FWD_DECL_TYPE_WITH_REFS( ProgressObserver );
@@ -410,7 +410,7 @@
     /*!
      * Adds the repository in \a info and returns the updated \ref RepoInfo 
object.
      */
-    expected<RepoInfo> addRepository( const RepoInfo & info, 
ProgressObserverRef myProgress = nullptr );
+    expected<RepoInfo> addRepository( const RepoInfo & info, const 
ProgressObserverRef myProgress = nullptr, const zypp::TriBool & forcedProbe = 
zypp::indeterminate );
 
     expected<void> addRepositories( const zypp::Url & url, ProgressObserverRef 
myProgress = nullptr );
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp/target/rpm/RpmDb.cc 
new/libzypp-17.37.12/zypp/target/rpm/RpmDb.cc
--- old/libzypp-17.37.11/zypp/target/rpm/RpmDb.cc       2025-07-14 
12:09:34.000000000 +0200
+++ new/libzypp-17.37.12/zypp/target/rpm/RpmDb.cc       2025-07-18 
22:21:30.000000000 +0200
@@ -2035,6 +2035,7 @@
   // to figure out which script is currently executed. Otherwise we
   // can't tell which output belongs to which script.
   static const str::regex rx( "^D: (%.*): (scriptlet start|running .* 
scriptlet)" );
+  static const str::regex rx2( "^Running (%[^)]*[)])$" );
   str::smatch what;
   std::string line;
   bool silent = true; // discard everything before 1st scriptlet
@@ -2046,12 +2047,21 @@
     if ( str::startsWith( line, "D:" ) ) {  // rpm debug output
       if ( str::regex_match( line, what, rx ) ) {
         // forward ripoff header
+        DBG << "Verbose RIPOFF:"+what[1] << endl;
         output_r( "RIPOFF:"+what[1] );
         if ( silent )
           silent = false;
       }
       continue;
     }
+    if ( str::regex_match( line, what, rx2 ) ) {  // preliminary for 1218459, 
but rpm needs fixing
+      // forward ripoff header
+      DBG << "NonVerbose RIPOFF:"+what[1] << endl;
+      // output_r( "RIPOFF:"+what[1] );
+      // if ( silent )
+      //   silent = false;
+      continue;
+    }
     if ( silent ) {
       continue;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp-curl/ng/network/zckhelper.cc 
new/libzypp-17.37.12/zypp-curl/ng/network/zckhelper.cc
--- old/libzypp-17.37.11/zypp-curl/ng/network/zckhelper.cc      2025-02-24 
14:59:49.000000000 +0100
+++ new/libzypp-17.37.12/zypp-curl/ng/network/zckhelper.cc      2025-07-18 
22:21:30.000000000 +0200
@@ -13,12 +13,300 @@
 #include <fstream>
 
 extern "C" {
-  #include <zck.h>
+#include <zck.h>
 }
 
 namespace zyppng {
 
-  bool ZckHelper::isZchunkFile(const zypp::Pathname &file) {
+  ZckError::ZckError(const std::string &msg_r) : Exception(msg_r)
+  { }
+
+  ZckError::ZckError(std::string &&msg_r) : Exception(std::move(msg_r))
+  { }
+
+  expected<void> ZckLoader::buildZchunkFile(const zypp::Pathname &target, 
const zypp::Pathname &delta, const std::optional<zypp::ByteCount> 
&expectedFileSize, const std::optional<zypp::ByteCount> &zcKHeaderSize)
+  {
+    if ( _state != Initial && _state != Finished ) {
+      return expected<void>::error( ZYPP_EXCPT_PTR(ZckError("Called 
buildZchunkFile in invalid state!")) );
+    }
+
+    _zchunkContext = zypp::AutoDispose<zckCtx *> ( zck_create(), []( auto ptr 
) { if ( ptr ) zck_free( &ptr ); } );
+    if( !_zchunkContext )
+      return expected<void>::error( ZYPP_EXCPT_PTR(ZckError( 
zypp::str::Format("Failed to create zchunk context: %1%") % zck_get_error(NULL) 
)) );
+
+    _targetFd = open( target.asString().c_str(), O_RDWR );
+    if( _targetFd < 0 )
+      return expected<void>::error( ZYPP_EXCPT_PTR(ZckError( 
zypp::str::Format("Unable to open %1%") % target )) );
+
+    if(!zck_init_adv_read(_zchunkContext, _targetFd))
+      return expected<void>::error( ZYPP_EXCPT_PTR(ZckError( 
zypp::str::Format( "Unable to init read for %1%: %2%") %  target % 
zck_get_error(_zchunkContext) )) );
+
+    _target = target;
+    _delta = delta;
+    _zcKHeaderSize = zcKHeaderSize;
+    _expectedFileSize = expectedFileSize;
+    _bytesReused = 0;
+
+    std::vector<Block> initialBlocks;
+    if ( _zcKHeaderSize ) {
+      Block b;
+      b._start = 0;
+      b._len   = *_zcKHeaderSize;
+      initialBlocks.push_back (b);
+      _state = DownloadHeader;
+    } else {
+      Block b;
+      b._start = 0;
+      b._len   = minZchunkDownloadSize();
+      initialBlocks.push_back (b);
+      _state = DownloadLead;
+    }
+
+    _sigBlocksRequired.emit( initialBlocks );
+    return expected<void>::success();
+  }
+
+  expected<void> ZckLoader::cont()
+  {
+    const auto &emitFailed = [this]( PrepareResult::Code code, std::string 
message ){
+      _state = Finished;
+      _sigFinished.emit( PrepareResult {
+                           ._code = code,
+                           ._blocks = std::vector<Block>(),
+                           ._bytesReused = 0,
+                           ._message = std::move(message),
+                         });
+
+      if ( _targetFd )
+        ftruncate ( _targetFd, 0 );
+
+      return expected<void>::success();
+    };
+
+    switch( _state ) {
+      case DownloadLead: {
+        // calling code claims to have downloaded the lead.
+        if ( !zck_read_lead( _zchunkContext ) )
+          return emitFailed( PrepareResult::Error, zypp::str::Format( "Unable 
to read lead from %1%: %2%") %  _target % zck_get_error(_zchunkContext) );
+
+        // get actual lead length, no need to fetch it again
+        const auto start = zck_get_lead_length(_zchunkContext);
+
+        // not adding the header checksums here, zck will validate it when 
reading the header
+        Block b;
+        b._start = start;
+        b._len   = zck_get_header_length(_zchunkContext) - start;
+
+        _state = DownloadHeader;
+        _sigBlocksRequired.emit( std::vector<Block>{b} );
+
+        break;
+      }
+      case DownloadHeader: {
+        // calling code claims to have downloaded the full header, lets check
+        if ( _zcKHeaderSize ) {
+          // if the zckHeaderSize was known initially the DownloadLead state 
was skipped. We need to read the lead here
+          if ( !zck_read_lead( _zchunkContext ) ) {
+            return emitFailed(  PrepareResult::Error, zypp::str::Format( 
"Unable to read lead from %1%: %2%") %  _target % zck_get_error(_zchunkContext) 
);
+          }
+        }
+
+        if(!zck_read_header(_zchunkContext)) {
+          return emitFailed( PrepareResult::Error, zypp::str::Format( "Unable 
to read the header from %1%: %2%") %  _target % zck_get_error(_zchunkContext) );
+        }
+
+        // yay we have downloaded the header , now we know all chunks from the 
target file. Next step is to calculate
+        // what we can reuse and request the missing chunks
+
+        zypp::AutoFD src_fd = open( _delta.asString().c_str(), O_RDONLY);
+        if(src_fd < 0) {
+          return emitFailed ( PrepareResult::Error, zypp::str::Format("Unable 
to open %1%") % _delta );
+        }
+
+        zypp::AutoDispose<zckCtx *> zck_src ( zck_create(), []( auto ptr ) { 
if ( ptr ) zck_free( &ptr ); } );
+        if( !zck_src ) {
+          return emitFailed ( PrepareResult::Error, zypp::str::Format("%1%") % 
zck_get_error(NULL) );
+        }
+
+        if(!zck_init_read(zck_src, src_fd)) {
+          return emitFailed ( PrepareResult::Error, zypp::str::Format( "Unable 
to open %1%: %2%") %  _delta % zck_get_error(zck_src) );
+        }
+
+        {
+          // Returns 0 for error, -1 for invalid checksum and 1 for valid 
checksum
+          switch ( zck_find_valid_chunks(_zchunkContext) ) {
+            case 0: { // Returns 0 if there was a error
+              return emitFailed ( PrepareResult::Error, zypp::str::Format( 
"Unable to open %1%: %2%") %  _target % zck_get_error(_zchunkContext) );
+            }
+            case 1: { // getting a 1 would mean the file is already complete, 
basically impossible but lets handle it anyway
+              _state = Finished;
+              _sigFinished.emit(PrepareResult {
+                                  ._code = PrepareResult::Success
+                                });
+              return expected<void>::success();
+            }
+          }
+
+          const auto srcHashType = zck_get_chunk_hash_type( _zchunkContext );
+          const auto targetHashType = zck_get_chunk_hash_type( _zchunkContext 
);
+
+          zypp::ByteCount fileSize = zck_get_length( _zchunkContext );
+          if ( _expectedFileSize && _expectedFileSize.value() != fileSize ) {
+            // check if the file size as reported by zchunk is equal to the 
one we expect
+            return emitFailed(
+                  PrepareResult::ExceedsMaxLen,
+                  zypp::str::Format("Zchunk header reports a different 
filesize than what was expected ( Zck: %1% != Exp: %2%).") % fileSize % 
*_expectedFileSize
+                  );
+          }
+
+          if ( ftruncate ( _targetFd, fileSize ) < 0 ) {
+            return emitFailed ( PrepareResult::Error, zypp::str::Format( 
"Failed to truncate file to required filesize.") );
+          }
+
+          if( srcHashType != targetHashType ) {
+            return emitFailed ( PrepareResult::Error, zypp::str::Format( 
"ERROR: Chunk hash types don't match. Source Hash: %1% vs Target Hash: %2%")
+                                % zck_hash_name_from_type ( srcHashType )
+                                % zck_hash_name_from_type ( targetHashType ) );
+          }
+
+          std::vector<Block> ranges;
+
+          if(!zck_copy_chunks( zck_src, _zchunkContext ))
+            return emitFailed ( PrepareResult::Error, zypp::str::Format( 
"Unable to copy chunks from deltafile.") );
+
+          // we calculate what is already downloaded by substracting the block 
sizes we still need to download from the full file size
+          auto bytesReused = fileSize;
+
+          auto chunk = zck_get_first_chunk( _zchunkContext );
+
+          if ( !chunk ) {
+            return emitFailed ( PrepareResult::Error, zypp::str::Format( 
"Unable to get first chunk: %1%.") % zck_get_error(_zchunkContext) );
+          }
+
+          do {
+            // Get validity of current chunk: 1 = valid, 0 = missing, -1 = 
invalid
+            if ( zck_get_chunk_valid( chunk ) == 1 )
+              continue;
+
+            zypp::AutoFREE<char> zckDigest( zck_get_chunk_digest( chunk ) );
+            UByteArray chksumVec = zypp::Digest::hexStringToUByteArray( 
std::string_view( zckDigest.value() ) );
+            std::string chksumName;
+            std::optional<size_t> chksumCompareLen;
+
+            switch ( targetHashType ) {
+              case ZCK_HASH_SHA1: {
+                chksumName = zypp::Digest::sha1();
+                break;
+              }
+              case ZCK_HASH_SHA256: {
+                chksumName = zypp::Digest::sha256();
+                break;
+              }
+              case ZCK_HASH_SHA512: {
+                chksumName = zypp::Digest::sha512();
+                break;
+              }
+              case ZCK_HASH_SHA512_128: {
+                // defined in zchunk as
+                // SHA-512/128 (first 128 bits of SHA-512 checksum)
+                chksumName = zypp::Digest::sha512();
+                chksumCompareLen = chksumVec.size();
+                break;
+              }
+              default: {
+                return emitFailed ( PrepareResult::Error, zypp::str::Format( 
"Unsupported chunk hash type: %1%.") % zck_hash_name_from_type( targetHashType 
) );
+              }
+            }
+
+            const auto s = static_cast<size_t>( zck_get_chunk_start( chunk ) );
+            const auto l = static_cast<size_t>( zck_get_chunk_comp_size ( 
chunk ) );
+
+            MIL_MEDIA << "Downloading block " << s << " with length " << l << 
" checksum " << zckDigest.value() << " type " << chksumName << std::endl;
+            ranges.push_back( Block {
+                                ._start = s,
+                                ._len   = l,
+                                ._chksumtype = chksumName,
+                                ._checksum  = std::move( chksumVec ),
+                                ._relevantDigestLen = 
std::move(chksumCompareLen)
+                              } );
+
+            // substract the block length from the already downloaded bytes 
size
+            bytesReused -= l;
+
+          } while ( (chunk = zck_get_next_chunk( chunk )) );
+
+
+          _state = DownloadChunks;
+          _bytesReused = bytesReused;
+          _sigBlocksRequired.emit( ranges );
+        }
+        break;
+      }
+      case DownloadChunks: {
+        // all data should be there now.
+
+        /* Validate the chunk and data checksums for the current file.
+         * Returns 0 for error, -1 for invalid checksum and 1 for valid 
checksum */
+        const auto res = zck_validate_checksums( _zchunkContext );
+        if ( res == 0 || res == -1 ) {
+          if( zck_is_error(nullptr) ) {
+            std::string err = zck_get_error(NULL);
+            zck_clear_error(NULL);
+            return emitFailed( PrepareResult::Error, std::move(err) );
+          }
+          if( zck_is_error(_zchunkContext) )
+            return emitFailed( PrepareResult::Error, 
zck_get_error(_zchunkContext) );
+          return emitFailed( PrepareResult::Error, "zck_validate_checksums 
returned a unknown error." );
+        }
+
+        _state = Finished;
+        PrepareResult pres;
+        pres._code = PrepareResult::Success;
+        pres._bytesReused = _bytesReused;
+        _sigFinished.emit(pres);
+        break;
+      }
+
+      case Initial:
+      case Finished: {
+        return expected<void>::error( ZYPP_EXCPT_PTR(ZckError( 
zypp::str::Format("Continue called in invalid state.") )) );
+      }
+    }
+    // continuation worked
+    return expected<void>::success();
+  }
+
+  void ZckLoader::setFailed(const std::string &msg)
+  {
+    _state = Finished;
+
+    if ( _targetFd )
+      ftruncate ( _targetFd, 0 );
+
+    _sigFinished.emit( PrepareResult {
+                         ._code = PrepareResult::Error,
+                         ._blocks = std::vector<Block>(),
+                         ._bytesReused = 0,
+                         ._message = msg,
+                       });
+  }
+
+  SignalProxy<void (const std::vector<ZckLoader::Block> &)> 
ZckLoader::sigBlocksRequired()
+  {
+    return _sigBlocksRequired;
+  }
+
+  SignalProxy<void (ZckLoader::PrepareResult)> ZckLoader::sigFinished()
+  {
+    return _sigFinished;
+  }
+
+  zypp::ByteCount ZckLoader::minZchunkDownloadSize()
+  {
+    return zck_get_min_download_size();
+  }
+
+  bool ZckLoader::isZchunkFile(const zypp::Pathname &file) {
     std::ifstream dFile(file.c_str());
     if (!dFile.is_open())
       return false;
@@ -31,14 +319,14 @@
     return (magic == std::string_view(lead.data(), lead.size()));
   }
 
-  ZckHelper::PrepareResult ZckHelper::prepareZck( const zypp::Pathname &delta, 
const zypp::Pathname &target, const zypp::ByteCount &expectedFileSize )
+  ZckLoader::PrepareResult ZckLoader::prepareZck( const zypp::Pathname &delta, 
const zypp::Pathname &target, const zypp::ByteCount &expectedFileSize )
   {
     const auto &setFailed = []( PrepareResult::Code code, std::string message 
){
       return PrepareResult {
         ._code = code,
-        ._blocks = std::vector<Block>(),
-        ._bytesReused = 0,
-        ._message = std::move(message),
+            ._blocks = std::vector<Block>(),
+            ._bytesReused = 0,
+            ._message = std::move(message),
       };
     };
 
@@ -94,79 +382,79 @@
 
     if( srcHashType != targetHashType )
       return setFailed ( PrepareResult::Error, zypp::str::Format( "ERROR: 
Chunk hash types don't match. Source Hash: %1% vs Target Hash: %2%")
-                        % zck_hash_name_from_type ( srcHashType )
-                        % zck_hash_name_from_type ( targetHashType ) );
+                         % zck_hash_name_from_type ( srcHashType )
+                         % zck_hash_name_from_type ( targetHashType ) );
 
     std::vector<Block> ranges;
 
     if(!zck_copy_chunks( zck_src, zckTarget ))
       return setFailed ( PrepareResult::Error, zypp::str::Format( "Unable to 
copy chunks from deltafile.") );
 
-        // we calculate what is already downloaded by substracting the block 
sizes we still need to download from the full file size
-        auto bytesReused = _fileSize;
+    // we calculate what is already downloaded by substracting the block sizes 
we still need to download from the full file size
+    auto bytesReused = _fileSize;
 
-        auto chunk = zck_get_first_chunk( zckTarget );
-        do {
-          // Get validity of current chunk: 1 = valid, 0 = missing, -1 = 
invalid
-          if ( zck_get_chunk_valid( chunk ) == 1 )
-            continue;
-
-          zypp::AutoFREE<char> zckDigest( zck_get_chunk_digest( chunk ) );
-          UByteArray chksumVec = zypp::Digest::hexStringToUByteArray( 
std::string_view( zckDigest.value() ) );
-          std::string chksumName;
-          std::optional<size_t> chksumCompareLen;
-
-          switch ( targetHashType ) {
-            case ZCK_HASH_SHA1: {
-              chksumName = zypp::Digest::sha1();
-              break;
-            }
-            case ZCK_HASH_SHA256: {
-              chksumName = zypp::Digest::sha256();
-              break;
-            }
-            case ZCK_HASH_SHA512: {
-              chksumName = zypp::Digest::sha512();
-              break;
-            }
-            case ZCK_HASH_SHA512_128: {
-              // defined in zchunk as
-              // SHA-512/128 (first 128 bits of SHA-512 checksum)
-              chksumName = zypp::Digest::sha512();
-              chksumCompareLen = chksumVec.size();
-              break;
-            }
-            default: {
-              return setFailed ( PrepareResult::Error, zypp::str::Format( 
"Unsupported chunk hash type: %1%.") % zck_hash_name_from_type( targetHashType 
) );
-            }
-          }
+    auto chunk = zck_get_first_chunk( zckTarget );
+    do {
+      // Get validity of current chunk: 1 = valid, 0 = missing, -1 = invalid
+      if ( zck_get_chunk_valid( chunk ) == 1 )
+        continue;
+
+      zypp::AutoFREE<char> zckDigest( zck_get_chunk_digest( chunk ) );
+      UByteArray chksumVec = zypp::Digest::hexStringToUByteArray( 
std::string_view( zckDigest.value() ) );
+      std::string chksumName;
+      std::optional<size_t> chksumCompareLen;
+
+      switch ( targetHashType ) {
+        case ZCK_HASH_SHA1: {
+          chksumName = zypp::Digest::sha1();
+          break;
+        }
+        case ZCK_HASH_SHA256: {
+          chksumName = zypp::Digest::sha256();
+          break;
+        }
+        case ZCK_HASH_SHA512: {
+          chksumName = zypp::Digest::sha512();
+          break;
+        }
+        case ZCK_HASH_SHA512_128: {
+          // defined in zchunk as
+          // SHA-512/128 (first 128 bits of SHA-512 checksum)
+          chksumName = zypp::Digest::sha512();
+          chksumCompareLen = chksumVec.size();
+          break;
+        }
+        default: {
+          return setFailed ( PrepareResult::Error, zypp::str::Format( 
"Unsupported chunk hash type: %1%.") % zck_hash_name_from_type( targetHashType 
) );
+        }
+      }
 
-          const auto s = static_cast<size_t>( zck_get_chunk_start( chunk ) );
-          const auto l = static_cast<size_t>( zck_get_chunk_comp_size ( chunk 
) );
+      const auto s = static_cast<size_t>( zck_get_chunk_start( chunk ) );
+      const auto l = static_cast<size_t>( zck_get_chunk_comp_size ( chunk ) );
 
-          MIL_MEDIA << "Downloading block " << s << " with length " << l << " 
checksum " << zckDigest.value() << " type " << chksumName << std::endl;
-          ranges.push_back( Block {
-            ._start = s,
-            ._len   = l,
-            ._chksumtype = chksumName,
-            ._checksum  = std::move( chksumVec ),
-            ._relevantDigestLen = std::move(chksumCompareLen)
-          } );
+      MIL_MEDIA << "Downloading block " << s << " with length " << l << " 
checksum " << zckDigest.value() << " type " << chksumName << std::endl;
+      ranges.push_back( Block {
+                          ._start = s,
+                          ._len   = l,
+                          ._chksumtype = chksumName,
+                          ._checksum  = std::move( chksumVec ),
+                          ._relevantDigestLen = std::move(chksumCompareLen)
+                        } );
 
-          // substract the block length from the already downloaded bytes size
-          bytesReused -= l;
+      // substract the block length from the already downloaded bytes size
+      bytesReused -= l;
 
-        } while ( (chunk = zck_get_next_chunk( chunk )) );
+    } while ( (chunk = zck_get_next_chunk( chunk )) );
 
-        return PrepareResult {
-          ._code = PrepareResult::Success,
+    return PrepareResult {
+      ._code = PrepareResult::Success,
           ._blocks = std::move(ranges),
           ._bytesReused = std::move(bytesReused),
           ._message = std::string()
-        };
+    };
   }
 
-  bool ZckHelper::validateZckFile(const zypp::Pathname &file, std::string 
&error)
+  bool ZckLoader::validateZckFile(const zypp::Pathname &file, std::string 
&error)
   {
     const auto &setFailed = [&]( std::string &&err ) {
       error = std::move(err);
@@ -201,8 +489,4 @@
     return true;
   }
 
-
-
-
-
 } // namespace zyppng
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libzypp-17.37.11/zypp-curl/ng/network/zckhelper.h 
new/libzypp-17.37.12/zypp-curl/ng/network/zckhelper.h
--- old/libzypp-17.37.11/zypp-curl/ng/network/zckhelper.h       2025-02-24 
14:59:49.000000000 +0100
+++ new/libzypp-17.37.12/zypp-curl/ng/network/zckhelper.h       2025-07-18 
22:21:30.000000000 +0200
@@ -17,10 +17,32 @@
 #include <zypp-curl/ng/network/curlmultiparthandler.h>
 #include <zypp-curl/ng/network/rangedesc.h>
 
+#include <zypp-core/AutoDispose.h>
+#include <zypp-core/zyppng/base/Base>
+
+extern "C" {
+  typedef struct zckCtx zckCtx;
+}
+
 namespace zyppng {
 
-  class ZckHelper {
+  class ZckError : public zypp::Exception
+  {
   public:
+    ZckError( const std::string & msg_r );
+    ZckError( std::string && msg_r );
+  };
+
+  class ZckLoader : public Base {
+  public:
+
+      enum State {
+        Initial,
+        DownloadLead,
+        DownloadHeader,
+        DownloadChunks,
+        Finished
+      };
 
     using Block = RangeDesc;
 
@@ -38,6 +60,41 @@
       std::string _message;
     };
 
+
+    /*!
+     * This function kickstarts the build process. The sigBlocksRequired and 
sigFinished signals need to be connected in order to
+     * download required blocks or get the finished event.
+     */
+    expected<void> buildZchunkFile( const zypp::Pathname &target, const 
zypp::Pathname &delta, const std::optional<zypp::ByteCount> &expectedFileSize, 
const std::optional<zypp::ByteCount> &zcKHeaderSize );
+
+    /*!
+     * Advances the statemachine after sigBlocksRequired was triggered and 
blocks have been downloaded
+     * into the targetFile
+     */
+    expected<void> cont();
+
+    /*!
+     * Advances the statemanchine into the failed state and emits sigFinished
+     */
+    void setFailed( const std::string &msg );
+
+    /**
+     * Signal to notify the caller about required blocks, once the blocks are 
downloaded call
+     * \ref cont to continue with the process
+     */
+    SignalProxy<void(const std::vector<Block> &)> sigBlocksRequired();
+
+    /**
+     * Called once the zchunk build process is finished, either with error or 
success
+     */
+    SignalProxy<void( PrepareResult )> sigFinished();
+
+
+    /**
+     * The minimum size to download to have enough data to know the full 
header size
+     */
+    static zypp::ByteCount minZchunkDownloadSize();
+
     /*!
      * Checks if a given file is a zck file
      */
@@ -53,6 +110,21 @@
      * Checks if a given zck file is internally valid
      */
     static bool validateZckFile( const zypp::Pathname &file, std::string 
&error );
+
+
+  private:
+    State _state = Initial;
+    zypp::AutoDispose<zckCtx *> _zchunkContext;
+    zypp::AutoFD _targetFd;
+    zypp::ByteCount _bytesReused = 0;
+
+    zypp::Pathname _target;
+    zypp::Pathname _delta;
+    std::optional<zypp::ByteCount> _expectedFileSize;
+    std::optional<zypp::ByteCount> _zcKHeaderSize;
+
+    Signal<void(const std::vector<Block> &)> _sigBlocksRequired;
+    Signal<void( PrepareResult )> _sigFinished;
   };
 }
 #endif

Reply via email to