Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package os-autoinst for openSUSE:Factory 
checked in at 2025-04-22 17:30:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/os-autoinst (Old)
 and      /work/SRC/openSUSE:Factory/.os-autoinst.new.30101 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "os-autoinst"

Tue Apr 22 17:30:19 2025 rev:512 rq:1271839 version:5.1745266261.8745de3

Changes:
--------
--- /work/SRC/openSUSE:Factory/os-autoinst/os-autoinst.changes  2025-03-28 
09:37:55.478353824 +0100
+++ /work/SRC/openSUSE:Factory/.os-autoinst.new.30101/os-autoinst.changes       
2025-04-22 17:30:54.317690278 +0200
@@ -1,0 +2,184 @@
+Mon Apr 21 20:11:11 UTC 2025 - ok...@suse.com
+
+- Update to version 5.1745266261.8745de3:
+  * tidy: Enforce blank lines before subs
+  * New script: os-autoinst-generate-needle-preview
+  * Revert removal of '%cmd' after regressions
+  * Remove unused variables and exports from testapi
+  * backend: Make screen check time exceed check configurable
+  * backend: Make stall detection factor configurable
+  * Retry syswrite in myjsonrpc if not all bytes were written
+  * Update Perl::Tidy to 20250311
+  * CI: Bump to codecov-action@v5
+  * Bring up network devices to avoid "(tapX): Operation not permitted"
+  * Prevent conflicts to ensure eth iface is assigned to one firewalld zone
+  * Mention for what asset types `autoinst_url` can be used
+  * Better error when syswrite fails in myjsonrpc
+  * Consistently use try/catch instead of 'if ' everywhere
+  * Enable validation of resumed asset downloads in svirt backend
+  * Avoid leftover rsync processes on svirt host
+  * Check for correct git warning when cloning an empty repository
+  * Adapt check for git error message to new version
+  * Fix regression from 055d2e67 in _set_ip arguments
+  * Ensure full coverage in the project
+  * Create test for script os-autoinst-openvswitch
+  * Enable is_shutdown to be used after "power('off')" on qemu
+  * Retry asset sync in svirt backend after timeouts
+  * testapi: allow keeping mouse in place after clicking
+  * script: Mark uncoverable package import as such
+  * codecov: Mark consoles/ as completely covered
+  * scripts: Rely on Pod::Usage being installed
+  * t: Cover invalid JSON in vars.json
+  * perltidy: Use new --pack-operator-types option
+  * perltidy: Update to 20250214.0.0
+  * Fix test API function `force_soft_failure`
+  * Fix return value of _dbus_call
+  * Fix log colors
+  * Use more Mojo::File operations in baseclass
+  * Use more Mojo::File operations in ocr.pm
+  * Use more Mojo::File operations in testapi.pm
+  * Use more Mojo::File operations in tools/
+  * t: Use Mojo::File in 04-check_vars_docu.t
+  * consoles: Simplify s3270 code
+  * Extract while loop body method in consoles::s3270
+  * Simplify consoles::s3270
+  * Add support for newline seperator in SCHEDULE variable
+  * Fix timeout of SSH commands after fc8ab5395 and ca4f085c
+  * Add unit test for code coverage of consoles/s3270.pm
+  * Remove undefined _kill_window() function from consoles/s3270.pm
+  * Use Feature::Compat::Try in testapi
+  * Use Feature::Compat::Try in script/os-autoinst-openvswitch
+  * Use Feature::Compat::Try in script/isotovideo
+  * Use Feature::Compat::Try in script/check_qemu_oom
+  * Use Feature::Compat::Try in osutils
+  * Use Feature::Compat::Try in consoles::sshXtermIPMI
+  * Use Feature::Compat::Try in consoles::VNC
+  * Use Feature::Compat::Try in consoles::VMWare
+  * Use Feature::Compat::Try in commands
+  * Use Feature::Compat::Try in bmwqemu
+  * Use Feature::Compat::Try in basetest
+  * Use Feature::Compat::Try in backend::qemu
+  * Use Feature::Compat::Try in backend::ipmi
+  * Use Feature::Compat::Try in backend::generalhw
+  * Use Feature::Compat::Try in backend::baseclass
+  * Use Feature::Compat::Try in autotest
+  * Use Feature::Compat::Try in OpenQA::Isotovideo::Proc
+  * Use Feature::Compat::Try in OpenQA::Isotovideo::Utils
+  * Use Feature::Compat::Try in OpenQA::Isotovideo::Runner
+  * Use Feature::Compat::Try in t
+  * Ensure a clean swtpm directory
+  * Use Feature::Compat::Try in place of Try::Tiny
+  * t: Add reason for undefined Pod::Coverage result
+  * Avoid duplicating common rsync arguments in svirt code
+  * Show download statistics in svirt backend when downloading assets
+  * Use distinct and lower timeout for rsync call in svirt backend
+  * Extend timeout for rsync commands done by the svirt backend to 15 min
+  * Add dependency on Feature::Compat::Try
+  * t: Consistently use Test::Exception method instead of manual eval checks
+  * t: Fix check for simplified Test::Exception
+  * Remove unused 'try' import
+  * Fix documentation for force_soft_failure and record_soft_failure
+  * t: Capture SYNC_ASSETS_HOOK debug output
+  * Remove unused module Test::MockModule from 01-test-needle
+  * Remove Test::Fatal dependency
+  * Modify connect_and_login() test to catch multiline carp warning
+  * Apply suggestions from code review
+  * Add unit tests for consoles/s3270.pm
+  * t: Use more simple prototyped Test::Exceptions functions
+  * t: Focus on using Test::Exception only instead of Test::Fatal
+  * t: Ensure we use implicit Test::Exception in all places
+  * Fix race condition when autotest terminates
+  * Make it obvious when autotest receives SIGTERM in any case
+  * Increase vnctest script coverage
+  * Remove call to unmock from code review suggestion
+  * Fix error handling when reading output of SSH commands after 0d09ec97e
+  * Remove time comparison with dv_timings_last_check
+  * Add complete statement coverage for consoles::sshVirtshSUT
+  * qemu: Use proper check for defined
+  * Fix error handling when reading output of SSH commands after 0d09ec97e
+  * qemu: Fix warning when saving non-attached storage
+  * Add full code coverage for consoles/sshXtermIPMI.pm
+  * Call SYNC_ASSETS_HOOK before downloading fresh needles too
+  * Add unit tests for consoles/sshXtermIPMI.pm
+  * Extend documentation of SSH related timeout parameters
+  * Allow specifying the timeout on `get_cmd_output` calls
+  * Avoid endless loop in case of SSH read errors in `check_ssh_serial`
+  * Add more code coverage for video_stream.pm
+  * Clone the disk image with nvram for vmware guest
+  * Update loadtestdir with correct paths
+  * Fix passing of variables
+  * Extract method in OpenQA::Isotovideo::Dewebsockify
+  * t: Fix 'The signatures feature is experimental' in t/39-dewebsockify.t
+  * Add test coverage for sshXtermVt
+  * Add coverage for tags subroutine when called with more than 2
+  * Update perltidy to 20250105
+  * t: Fix hidden output of 'diag explain'
+  * Add test covering dewebsockify modulino
+  * Make script/dewebsockify a Modulino
+  * Improve test for websocket error handling
+  * Update Perl::Tidy to 20240903
+  * Add test for needles::tags subroutine
+  * Remove save subroutine since is not used anymore
+  * Refactor _load_image bmwqemu::diag in one line
+  * Add test for needle tag duplication
+  * Add handle needle new invalid click point
+  * Add handle broken json file for new needle
+  * Add test for json file not under needle directory
+  * Correct link to ci badge
+  * autotest/loadtest: Update test fullname along with name when duplicated
+  * Add subtests for commands.pm
+  * Fix warn+return precendence
+  * Remove extra arguments from testapi::send_key()
+  * Modify loadtestdir in autotest for more code coverage
+  * t: cover both old and new qemu paths in 18-backend-qemu.t
+  * Revert incorrect fixes for qemu test coverage
+  * Remove unreachable states in tests 18-backend-qemu
+  * Fix code coverage for qemu.pm
+  * t: fix tests for #2550 for old and new qemu
+  * Fix test of qemu backend
+  * Enable multifd support
+  * Remove redundant newline in "GOT GO" message
+  * autotest: Simplify with post-if
+  * Add unit test for 'ensure_installed' to improve code coverage
+  * Drop some orphaned lines about gocrbin
+  * Add more subtests for distribution.pm
+  * Replace print with bmwqemu::diag in autotest.pm
+  * Add subtest for autotest.pm
+  * Add test for the old net ssh2 error
+  * Slightly simplify autotest
+  * Remove _typing_limit subroutine because it's never used
+  * Update t/08-autotest.t
+  * Remove subs on vnc_base that are already declared on base
+  * Enable more unit test code for codecoverage
+  * Add more subtests for autotest.pm
+  * Add script/check_qemu_oom to fully covered paths on codecov
+  * Add lockapi fully coverage 100% in codecov
+  * Add lockapi::mutex_wait test in t/30-mmapi.t
+  * Skip 28-signalblocker test in qemu emulation
+  * Export handle_read_error function from read_json
+  * Set a bmwqemu diag uncoverable
+  * Refactor utility functions for myjsonrpc
+  * Add coverage test for written bytes errors
+  * Avoid adding message about termination from myjsonrpc as reason
+  * Fix unhandled output "Sending tests_done" in t/08-autotest.t
+  * Avoid Perl warning about when handling tags to assert
+  * Ensure full statement coverage in consoles::sshVirtsh
+  * Extend sshVirtsh console test coverage
+  * Add logging and error handling
+  * video_stream: add support for ustreamer >= 6.10
+  * video_stream: add support for RGB3 format
+  * video_stream: typo fix
+  * video_stream: adjust raw sink name for ustreamer >= 6.5
+  * Fix: console reset on milestone loading
+  * codecov: Mark basetest as completely covered
+  * basetest: Simplify record_screenfail to increase coverage
+  * Remove obsolete basetest::ocr_checklist
+  * cv: Mark extraordinary error handling as uncoverable
+  * Handle PID logging in Xvnc test
+  * Cover deprecation logging
+  * Remove obsolete amt backend
+  * Make actually use of `%python_support_requires` for Python support
+  * snd2png: Clamping fix
+  * dist: Bump version to semver-compliant 5
+
+-------------------------------------------------------------------

Old:
----
  os-autoinst-5.1743091574.1f9ae10.obscpio

New:
----
  os-autoinst-5.1745266261.8745de3.obscpio

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

Other differences:
------------------
++++++ os-autoinst-devel-test.spec ++++++
--- /var/tmp/diff_new_pack.2CysUD/_old  2025-04-22 17:30:55.273730437 +0200
+++ /var/tmp/diff_new_pack.2CysUD/_new  2025-04-22 17:30:55.273730437 +0200
@@ -18,7 +18,7 @@
 
 %define         short_name os-autoinst-devel
 Name:           %{short_name}-test
-Version:        5.1743091574.1f9ae10
+Version:        5.1745266261.8745de3
 Release:        0
 Summary:        Test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ os-autoinst-openvswitch-test.spec ++++++
--- /var/tmp/diff_new_pack.2CysUD/_old  2025-04-22 17:30:55.297731445 +0200
+++ /var/tmp/diff_new_pack.2CysUD/_new  2025-04-22 17:30:55.297731445 +0200
@@ -19,7 +19,7 @@
 %define name_ext -test
 %define         short_name os-autoinst-openvswitch
 Name:           %{short_name}%{?name_ext}
-Version:        5.1743091574.1f9ae10
+Version:        5.1745266261.8745de3
 Release:        0
 Summary:        test package for %{short_name}
 License:        GPL-2.0-or-later

++++++ os-autoinst-test.spec ++++++
--- /var/tmp/diff_new_pack.2CysUD/_old  2025-04-22 17:30:55.321732454 +0200
+++ /var/tmp/diff_new_pack.2CysUD/_new  2025-04-22 17:30:55.325732622 +0200
@@ -19,7 +19,7 @@
 %define name_ext -test
 %define         short_name os-autoinst
 Name:           %{short_name}%{?name_ext}
-Version:        5.1743091574.1f9ae10
+Version:        5.1745266261.8745de3
 Release:        0
 Summary:        test package for os-autoinst
 License:        GPL-2.0-or-later

++++++ os-autoinst.spec ++++++
--- /var/tmp/diff_new_pack.2CysUD/_old  2025-04-22 17:30:55.357733966 +0200
+++ /var/tmp/diff_new_pack.2CysUD/_new  2025-04-22 17:30:55.361734133 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           os-autoinst
-Version:        5.1743091574.1f9ae10
+Version:        5.1745266261.8745de3
 Release:        0
 Summary:        OS-level test automation
 License:        GPL-2.0-or-later

++++++ os-autoinst-5.1743091574.1f9ae10.obscpio -> 
os-autoinst-5.1745266261.8745de3.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/.github/workflows/ci.yml 
new/os-autoinst-5.1745266261.8745de3/.github/workflows/ci.yml
--- old/os-autoinst-5.1743091574.1f9ae10/.github/workflows/ci.yml       
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/.github/workflows/ci.yml       
2025-04-21 22:11:01.000000000 +0200
@@ -13,7 +13,7 @@
       - name: Static checks, unit- and integration tests
         run: tools/container_run_ci
       - name: Upload coverage to Codecov
-        uses: codecov/codecov-action@v4
+        uses: codecov/codecov-action@v5
         with:
           # should not be necessary for public repos, but might help avoid 
sporadic upload token errors
           token: ${{ secrets.CODECOV_TOKEN }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/.perltidyrc 
new/os-autoinst-5.1745266261.8745de3/.perltidyrc
--- old/os-autoinst-5.1743091574.1f9ae10/.perltidyrc    2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/.perltidyrc    2025-04-21 
22:11:01.000000000 +0200
@@ -3,7 +3,7 @@
 --character-encoding=none
 --no-valign
 -l=160
--fbl     # don't change blank lines
+--noblanks-before-comments
 -fnl     # don't remove new lines
 -nsfs    # no spaces before semicolons
 -baao    # space after operators
@@ -13,3 +13,6 @@
 -sbt=2   # no spaces around {}
 -sct     # stack closing tokens )}
 --pack-operator-types='->' # allow chained method calls on one line
+--blanks-before-subs
+--keep-old-blank-lines=2 # keep all blank lines
+--noblanks-before-blocks
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/CMakeLists.txt 
new/os-autoinst-5.1745266261.8745de3/CMakeLists.txt
--- old/os-autoinst-5.1743091574.1f9ae10/CMakeLists.txt 2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/CMakeLists.txt 2025-04-21 
22:11:01.000000000 +0200
@@ -205,6 +205,11 @@
     DESTINATION "${CMAKE_INSTALL_BINDIR}"
     PERMISSIONS ${EXECUTABLE_PERMISSIONS}
 )
+install(
+    FILES 
"${CMAKE_CURRENT_SOURCE_DIR}/script/os-autoinst-generate-needle-preview"
+    DESTINATION "${CMAKE_INSTALL_BINDIR}"
+    PERMISSIONS ${EXECUTABLE_PERMISSIONS}
+)
 foreach (FILE README.asciidoc COPYING ${GENERATED_DOC_FILES})
     install(FILES "${FILE}" DESTINATION "${OS_AUTOINST_DOC_DIR}")
 endforeach ()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Isotovideo/Interface.pm 
new/os-autoinst-5.1745266261.8745de3/OpenQA/Isotovideo/Interface.pm
--- old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Isotovideo/Interface.pm 
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/OpenQA/Isotovideo/Interface.pm 
2025-04-21 22:11:01.000000000 +0200
@@ -9,7 +9,7 @@
 # -> increment on every change of such APIs
 # -> never move that variable to another place (when refactoring)
 #    because it may be accessed by the tests itself
-our $version = 43;
+our $version = 44;
 
 # major version of the (web socket) API relevant to the developer mode
 # -> increment when making non-backward compatible changes to that API
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Isotovideo/Utils.pm 
new/os-autoinst-5.1745266261.8745de3/OpenQA/Isotovideo/Utils.pm
--- old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Isotovideo/Utils.pm     
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/OpenQA/Isotovideo/Utils.pm     
2025-04-21 22:11:01.000000000 +0200
@@ -217,6 +217,7 @@
 Cloning may fail up to C<retry_count> times with a delay of C<retry_interval> 
seconds.
 
 =cut
+
 sub checkout_git_repo_and_branch ($dir_variable, %args) {
     my $dir = $bmwqemu::vars{$dir_variable} // $args{repo};
     return undef unless defined $dir;
@@ -259,6 +260,7 @@
 If no wheels are configured the function returns early.
 
 =cut
+
 sub checkout_wheels ($case_dir, $wheels_dir = undef) {
     my $specfile = path($case_dir, 'wheels.yaml');
     return 1 unless -e $specfile;
@@ -299,6 +301,7 @@
     checkout_git_refspec('/path/to/casedir', 'TEST_GIT_REFSPEC');
 
 =cut
+
 sub checkout_git_refspec ($dir, $refspec_variable) {
     return undef unless defined $dir;
     if (my $refspec = $bmwqemu::vars{$refspec_variable}) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Qemu/BlockDev.pm 
new/os-autoinst-5.1745266261.8745de3/OpenQA/Qemu/BlockDev.pm
--- old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Qemu/BlockDev.pm        
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/OpenQA/Qemu/BlockDev.pm        
2025-04-21 22:11:01.000000000 +0200
@@ -74,6 +74,7 @@
 To avoid memory leaks we weaken this reference.
 
 =cut
+
 sub overlay ($self, $ol) {
     return $self->{overlay} unless defined $ol;
     $self->{overlay} = $ol;
@@ -143,6 +144,7 @@
 creating.
 
 =cut
+
 sub gen_qemu_img_cmdlines ($self) {
     my $backing_file = $self->backing_file;
     my @cmdlns = defined $backing_file ? $backing_file->gen_qemu_img_cmdlines 
: ();
@@ -163,6 +165,7 @@
 this will return it in an array so that the caller can unlink it.
 
 =cut
+
 sub gen_unlink_list ($self) {
     return () unless $self->needs_creating;
     return ($self->file, $self->backing_file->gen_unlink_list())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Qemu/BlockDevConf.pm 
new/os-autoinst-5.1745266261.8745de3/OpenQA/Qemu/BlockDevConf.pm
--- old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Qemu/BlockDevConf.pm    
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/OpenQA/Qemu/BlockDevConf.pm    
2025-04-21 22:11:01.000000000 +0200
@@ -26,6 +26,7 @@
 Add an existing image file at the bottom/start of a block device chain.
 
 =cut
+
 sub add_existing_base ($self, $id, $file_name, $size) {
     $file_name //= $id;
 
@@ -41,6 +42,7 @@
 created by this function, this just updates the object model.
 
 =cut
+
 sub add_new_base ($self, $id, $file_name, $size) {
     $file_name //= $id;
 
@@ -53,6 +55,7 @@
 Add an existing image file as the overlay of $backing_file.
 
 =cut
+
 sub add_existing_overlay ($self, $id, $backing_file) {
     my $ol = OpenQA::Qemu::BlockDev->new()
       ->node_name($id)
@@ -93,6 +96,7 @@
 Create a new drive device and qcow2 image.
 
 =cut
+
 sub add_new_drive ($self, $id, $model, $size, $num_queues = undef, 
$sector_size = undef) {
     my $base_drive = $self->add_new_base($id, $id, $size);
     return $self->_push_new_drive_dev($id, $base_drive, $model, $num_queues, 
$sector_size);
@@ -104,6 +108,7 @@
 new overlay is created so that the existing qcow2 image is not modified.
 
 =cut
+
 sub add_existing_drive ($self, $id, $file_name, $model, $size, $num_queues = 
undef, $sector_size = undef) {
     my $base_drive = $self->add_existing_base($id, $file_name, 
$size)->implicit(1)->deduce_driver;
     my $overlay = $self->add_new_overlay($id . OVERLAY_POSTFIX . '0', 
$base_drive);
@@ -119,6 +124,7 @@
 underlying image.
 
 =cut
+
 sub add_iso_drive ($self, $id, $file_name, $model, $size) {
     my $base_drive = $self->add_existing_base($id, $file_name, $size)
       ->implicit(1)
@@ -134,6 +140,7 @@
 variables. See the OpenQA::Qemu::PFlashDevice class.
 
 =cut
+
 sub add_pflash_drive ($self, $id, $file_name, $size) {
     my $base_drive = $self->add_existing_base($id, $file_name, 
$size)->implicit(1)->deduce_driver;
     my $overlay = $self->add_new_overlay($id . OVERLAY_POSTFIX . '0', 
$base_drive);
@@ -151,6 +158,7 @@
 multiple connections to simulate multipath.
 
 =cut
+
 sub add_path_to_drive ($self, $id, $drive, $controller) {
     my $dp = OpenQA::Qemu::DrivePath->new()
       ->controller($controller)
@@ -167,6 +175,7 @@
 function will not mark the overlay for creation by qemu-img.
 
 =cut
+
 sub add_snapshot_to_drive ($self, $drive, $snapshot) {
     my $id = $drive->id . OVERLAY_POSTFIX . $drive->new_overlay_id;
 
@@ -185,6 +194,7 @@
 something unexpected. Also init_blockdev_images needs to be run after this.
 
 =cut
+
 sub revert_to_snapshot ($self, $drive, $snapshot) {
     my @del_files = ();
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Qemu/Proc.pm 
new/os-autoinst-5.1745266261.8745de3/OpenQA/Qemu/Proc.pm
--- old/os-autoinst-5.1743091574.1f9ae10/OpenQA/Qemu/Proc.pm    2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/OpenQA/Qemu/Proc.pm    2025-04-21 
22:11:01.000000000 +0200
@@ -70,6 +70,7 @@
 in the array will have '-' prepended to it.
 
 =cut
+
 sub static_param ($self, @args) {
     if (@args < 2) {
         push(@{$self->_static_params}, '-' . $args[0]);
@@ -85,6 +86,7 @@
 controllers for simple configurations.
 
 =cut
+
 sub configure_controllers ($self, $vars) {
     # Setting the HD or CD model to a type of SCSI controller has been
     # deprecated for a long time.
@@ -146,6 +148,7 @@
 Configure disk drives and their block device backing chains. See 
BlockDevConf.pm.
 
 =cut
+
 sub configure_blockdevs ($self, $bootfrom, $basedir, $vars) {
     my $bdc = $self->blockdev_conf;
     my @scsi_ctrs = $self->controller_conf->get_controllers(qr/scsi/);
@@ -238,6 +241,7 @@
 other block devices which slightly complicates things. See BlockDevConf.pm.
 
 =cut
+
 sub configure_pflash ($self, $vars) {
     my $bdc = $self->blockdev_conf;
 
@@ -275,6 +279,7 @@
 Generate the QEMU command line arguments from our object model.
 
 =cut
+
 sub gen_cmdline ($self) {
     return ($self->qemu_bin,
         @{$self->_static_params},
@@ -306,6 +311,7 @@
 This should only be called when QEMU is not running.
 
 =cut
+
 sub init_blockdev_images ($self) {
     for my $file ($self->blockdev_conf->gen_unlink_list()) {
         no autodie 'unlink';
@@ -329,6 +335,7 @@
 thing as performing an offline migration.
 
 =cut
+
 sub export_blockdev_images ($self, $filter, $img_dir, $name, 
$qemu_compress_qcow) {
     my $count = 0;
 
@@ -391,6 +398,7 @@
 using the JSON QAPI. QMP and QAPI are documented in the QEMU source tree.
 
 =cut
+
 sub connect_qmp ($self) {
     my $sk;
     osutils::attempt {
@@ -420,6 +428,7 @@
 storage as well as its CPU.
 
 =cut
+
 sub revert_to_snapshot ($self, $name) {
     my $bdc = $self->blockdev_conf;
 
@@ -445,6 +454,7 @@
 Serialise our object model of QEMU to JSON and return the JSON text.
 
 =cut
+
 sub serialise_state ($self) {
     return encode_json({
             blockdev_conf => $self->blockdev_conf->to_map(),
@@ -458,6 +468,7 @@
 Save our object model of QEMU to a file.
 
 =cut
+
 sub save_state ($self) {
     if ($self->has_state) {
         bmwqemu::fctinfo('Saving QEMU state to ' . STATE_FILE);
@@ -474,6 +485,7 @@
 Deserialise our object model from a string of JSON text.
 
 =cut
+
 sub deserialise_state ($self, $json) {
     my $state_map = decode_json($json);
 
@@ -491,6 +503,7 @@
 Load our object model of QEMU from a file.
 
 =cut
+
 sub load_state ($self) {
     # In order to remove this, you need to merge the new state with the
     # existing state from disk without breaking existing snapshots (block
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/autotest.pm 
new/os-autoinst-5.1745266261.8745de3/autotest.pm
--- old/os-autoinst-5.1743091574.1f9ae10/autotest.pm    2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/autotest.pm    2025-04-21 
22:11:01.000000000 +0200
@@ -29,6 +29,7 @@
 our $isotovideo;
 our $process;
 our $tests_running = 0;
+
 =head1 Introduction
 
 OS Autoinst decides which test modules to run based on a distribution specific
@@ -362,6 +363,7 @@
 }
 
 my $failed_command;
+
 sub pause_on_failure ($reason, $command = undef) {
     # avoid handling a failing command again (via the die handler) after the 
test execution has been resumed
     if (!defined $command && $failed_command) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/backend/baseclass.pm 
new/os-autoinst-5.1745266261.8745de3/backend/baseclass.pm
--- old/os-autoinst-5.1743091574.1f9ae10/backend/baseclass.pm   2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/backend/baseclass.pm   2025-04-21 
22:11:01.000000000 +0200
@@ -65,6 +65,8 @@
     $self->{ssh_connections} = {};
     $self->{xres} = $bmwqemu::vars{XRES} // 1024;
     $self->{yres} = $bmwqemu::vars{YRES} // 768;
+    $self->{stall_detect_factor} = $bmwqemu::vars{STALL_DETECT_FACTOR} // 20;
+    $self->{needle_check_factor} = $bmwqemu::vars{NEEDLE_CHECK_FACTOR} // 1;
 
     return $self;
 }
@@ -217,7 +219,7 @@
         }
 
         # if we got stalled for a long time, we assume bad hardware and report 
it
-        if ($self->assert_screen_last_check && $now - $self->last_screenshot > 
$self->screenshot_interval * 20) {
+        if ($self->assert_screen_last_check && $now - $self->last_screenshot > 
$self->screenshot_interval * $self->{stall_detect_factor}) {
             $self->stall_detected(1);
             my $diff = $now - $self->last_screenshot;
             bmwqemu::fctwarn "There is some problem with your environment, we 
detected a stall for $diff seconds";
@@ -712,6 +714,7 @@
 module after the snapshot.
 
 =cut
+
 sub save_console_snapshots ($self, $name) {
     for my $console (keys %{$testapi::distri->{consoles}}) {
         my $console_info = $self->console($console);
@@ -725,6 +728,7 @@
 in the same state as when the snapshot was taken.
 
 =cut
+
 sub load_console_snapshots ($self, $name) {
     for my $console (keys %{$testapi::distri->{consoles}}) {
         my $console_info = $self->console($console);
@@ -1038,7 +1042,7 @@
     }
 
     $watch->stop();
-    if ($watch->as_data()->{total_time} > $self->screenshot_interval) {
+    if ($watch->as_data()->{total_time} > $self->screenshot_interval * 
$self->{needle_check_factor}) {
         bmwqemu::fctwarn sprintf(
             "check_asserted_screen took %.2f seconds for %d candidate needles 
- make your needles more specific",
             $watch->as_data()->{total_time},
@@ -1295,6 +1299,7 @@
    frequently enough.
 
 =cut
+
 sub run_ssh_cmd ($self, $cmd, %args) {
     $args{wantarray} //= 0;
     $args{keep_open} //= 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/backend/qemu.pm 
new/os-autoinst-5.1745266261.8745de3/backend/qemu.pm
--- old/os-autoinst-5.1743091574.1f9ae10/backend/qemu.pm        2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/backend/qemu.pm        2025-04-21 
22:11:01.000000000 +0200
@@ -1117,6 +1117,7 @@
 with the getfd command.
 
 =cut
+
 sub handle_qmp_command ($self, $cmd, %optargs) {
     $optargs{fatal} ||= 0;
     my $sk = $self->{qmpsocket};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/backend/svirt.pm 
new/os-autoinst-5.1745266261.8745de3/backend/svirt.pm
--- old/os-autoinst-5.1743091574.1f9ae10/backend/svirt.pm       2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/backend/svirt.pm       2025-04-21 
22:11:01.000000000 +0200
@@ -234,6 +234,7 @@
 C<$args{port}> used non-default port
 C<$args{devname}> used device name
 =cut
+
 sub open_serial_console_via_ssh ($self, $name, %args) {
     bmwqemu::log_call(name => $name, %args);
     my ($chan, $cmd, $cmd_full, $ret, $ssh, $stderr, $stdout);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/basetest.pm 
new/os-autoinst-5.1745266261.8745de3/basetest.pm
--- old/os-autoinst-5.1743091574.1f9ae10/basetest.pm    2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/basetest.pm    2025-04-21 
22:11:01.000000000 +0200
@@ -434,6 +434,7 @@
 Record result file to be parsed when evaluating test results, for example
 within the openQA web interface.
 =cut
+
 sub record_resultfile ($self, $title, $output, %nargs) {
     my $filename = $self->next_resultname('txt', $nargs{resultname});
     my $detail = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/bmwqemu.pm 
new/os-autoinst-5.1745266261.8745de3/bmwqemu.pm
--- old/os-autoinst-5.1743091574.1f9ae10/bmwqemu.pm     2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/bmwqemu.pm     2025-04-21 
22:11:01.000000000 +0200
@@ -291,6 +291,7 @@
 
 Just a random string useful for pseudo security or temporary files.
 =cut
+
 sub random_string ($count) {
     $count //= 4;
     my $string;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/consoles/serial_screen.pm 
new/os-autoinst-5.1745266261.8745de3/consoles/serial_screen.pm
--- old/os-autoinst-5.1743091574.1f9ae10/consoles/serial_screen.pm      
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/consoles/serial_screen.pm      
2025-04-21 22:11:01.000000000 +0200
@@ -47,6 +47,7 @@
 name to terminal code mappings.
 
 =cut
+
 sub send_key ($self, $nargs) {
     croak $trying_to_use_keys unless $nargs->{key} eq 'ret';
     $nargs->{text} = "\n";
@@ -77,6 +78,7 @@
 consoles.
 
 =cut
+
 sub type_string ($self, $nargs) {
     my $fd = $self->{fd_write};
 
@@ -133,6 +135,7 @@
 just read once.
 
 =cut
+
 sub do_read {    # no:style:signatures
     my ($self, undef, %args) = @_;
     my $buffer = '';
@@ -192,6 +195,7 @@
 on failure.
 
 =cut
+
 sub read_until ($self, $pattern, $timeout, %nargs) {
     my $fd = $self->{fd_read};
     my $buflen = $nargs{buffer_size} || SOCKET_READ_BUFFER_SIZE;
@@ -267,6 +271,7 @@
 no information available about what data is expected to be available.
 
 =cut
+
 sub peak ($self, %nargs) {
     my $buflen = $nargs{buffer_size} || SOCKET_READ_BUFFER_SIZE;
     my $total_read = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/consoles/sshVirtsh.pm 
new/os-autoinst-5.1745266261.8745de3/consoles/sshVirtsh.pm
--- old/os-autoinst-5.1743091574.1f9ae10/consoles/sshVirtsh.pm  2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/consoles/sshVirtsh.pm  2025-04-21 
22:11:01.000000000 +0200
@@ -669,6 +669,7 @@
 username.
 For further arguments see C<baseclass:run_ssh_cmd()>.
 =cut
+
 sub run_cmd ($self, $cmd, %args) {
     my %credentials = $self->get_ssh_credentials($args{domain});
     delete $args{domain};
@@ -698,6 +699,7 @@
 I<stderr>.
 This function is B<deprecated>, you should use C<<$svirt->run_cmd()>> instead.
 =cut
+
 sub get_cmd_output ($self, $cmd, $args = {}) {
     my (undef, $stdout, $stderr) = $self->backend->run_ssh_cmd($cmd, 
$self->get_ssh_credentials($args->{domain}), timeout => $args->{timeout}, 
wantarray => 1);
     return $args->{wantarray} ? [$stdout, $stderr] : $stdout;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/consoles/virtio_terminal.pm 
new/os-autoinst-5.1745266261.8745de3/consoles/virtio_terminal.pm
--- old/os-autoinst-5.1743091574.1f9ae10/consoles/virtio_terminal.pm    
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/consoles/virtio_terminal.pm    
2025-04-21 22:11:01.000000000 +0200
@@ -121,6 +121,7 @@
 otherwise it dies.
 
 =cut
+
 sub open_pipe ($self) {
     bmwqemu::log_call(pipe_prefix => $self->{pipe_prefix});
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/cpanfile 
new/os-autoinst-5.1745266261.8745de3/cpanfile
--- old/os-autoinst-5.1743091574.1f9ae10/cpanfile       2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/cpanfile       2025-04-21 
22:11:01.000000000 +0200
@@ -101,7 +101,7 @@
     requires 'Code::TidyAll';
     requires 'Devel::Cover';
     requires 'Module::CPANfile';
-    requires 'Perl::Tidy', '== 20250214.0.0';
+    requires 'Perl::Tidy', '== 20250311.0.0';
     requires 'Template::Toolkit';
 
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/dependencies.yaml 
new/os-autoinst-5.1745266261.8745de3/dependencies.yaml
--- old/os-autoinst-5.1743091574.1f9ae10/dependencies.yaml      2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/dependencies.yaml      2025-04-21 
22:11:01.000000000 +0200
@@ -52,7 +52,7 @@
   perl(Devel::Cover):
   perl(Module::CPANfile):
   perl(Template::Toolkit):
-  perl(Perl::Tidy): == 20250214.0.0
+  perl(Perl::Tidy): == 20250311.0.0
   ShellCheck:
   shfmt:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/distribution.pm 
new/os-autoinst-5.1745266261.8745de3/distribution.pm
--- old/os-autoinst-5.1743091574.1f9ae10/distribution.pm        2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/distribution.pm        2025-04-21 
22:11:01.000000000 +0200
@@ -226,6 +226,7 @@
 $serial_term_prompt.
 
 =cut
+
 sub script_output ($self, $script, @args) {
     my %args = testapi::compat_args(
         {
@@ -327,6 +328,7 @@
     );
 
 =cut
+
 sub set_expected_serial_failures ($self, $failures) {
     $self->{serial_failures} = $failures;
 }
@@ -347,6 +349,7 @@
     );
 
 =cut
+
 sub set_expected_autoinst_failures ($self, $failures) {
     $self->{autoinst_failures} = $failures;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/doc/backend_vars.asciidoc 
new/os-autoinst-5.1745266261.8745de3/doc/backend_vars.asciidoc
--- old/os-autoinst-5.1743091574.1f9ae10/doc/backend_vars.asciidoc      
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/doc/backend_vars.asciidoc      
2025-04-21 22:11:01.000000000 +0200
@@ -24,6 +24,8 @@
 NO_DEBUG_IO;boolean;0;Disable the I/O debug output in case of needle 
comparison times longer than expected
 OSUTILS_WAIT_ATTEMPT_INTERVAL;float;1;The interval in seconds between 
"attempts" in osutils, e.g. used for connections to qemu qmp backend
 SCREENSHOTINTERVAL;float;0.5;The interval in seconds at which screenshots are 
taken internally
+STALL_DETECT_FACTOR;float;20;Report test execution as stalled if console 
screen check interval takes longer than SCREENSHOTINTERVAL multiplied with this 
factor
+NEEDLE_CHECK_FACTOR;float;20;Report warning if screen check interval takes 
longer than SCREENSHOTINTERVAL multiplied with this factor
 SSH_COMMAND_TIMEOUT_S;integer;300;Timeout in seconds for any SSH based command 
in SSH based consoles, disabled for a value of 0. It can be overriden by 
particular run_ssh_cmd() calls. Checkout the documentation of this function for 
details.
 SSH_CONNECT_RETRY;integer;5;Maximum retries to connect to SSH based console 
targets
 SSH_CONNECT_RETRY_INTERVAL;float;10;Interval in seconds between retries to 
connect to SSH based console targets. Related to SSH_CONNECT_RETRY
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/mmapi.pm 
new/os-autoinst-5.1745266261.8745de3/mmapi.pm
--- old/os-autoinst-5.1743091574.1f9ae10/mmapi.pm       2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/mmapi.pm       2025-04-21 
22:11:01.000000000 +0200
@@ -249,6 +249,7 @@
 Wait while any scheduled children exist.
 
 =cut
+
 sub wait_for_children_to_start () {
     while (1) {
         my $children = get_children() // die 'Failed to wait for children to 
start';
@@ -270,6 +271,7 @@
 
 Query openQA's API to retrieve the current job ID
 =cut
+
 sub get_current_job_id () {
     my $tx = api_call_2(get => 'whoami', undef, $CODES_EXPECTED_BY_MMAPI);
     return undef if handle_api_error($tx, 'whoami', $CODES_EXPECTED_BY_MMAPI);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/myjsonrpc.pm 
new/os-autoinst-5.1745266261.8745de3/myjsonrpc.pm
--- old/os-autoinst-5.1743091574.1f9ae10/myjsonrpc.pm   2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/myjsonrpc.pm   2025-04-21 
22:11:01.000000000 +0200
@@ -17,7 +17,7 @@
 # hash for keeping state
 our $sockets;
 
-sub _syswrite($to_fd, $json) { syswrite($to_fd, $json) }
+sub _syswrite($to_fd, $json, $length = undef, $offset = undef) { 
syswrite($to_fd, $json, $length, $offset) }
 
 sub is_debug () { DEBUG_JSON || $bmwqemu::vars{DEBUG_JSON_RPC} }
 
@@ -47,10 +47,14 @@
     $json .= "\n";
 
     confess 'myjsonrpc: called on undefined file descriptor' unless defined 
$to_fd;
-    my $written_bytes = _syswrite($to_fd, $json);
-    if (!$written_bytes || $written_bytes != length($json)) {
-        die('myjsonrpc: remote end terminated connection, stopping') if 
!DEBUG_JSON && $! =~ qr/Broken pipe/;
-        confess sprintf "syswrite failed: err: '%s'; written_bytes: %d/%d; 
JSON: '%s'", $!, $written_bytes, length($json), $json;
+    my $written_bytes = 0;
+    my $bytes_to_write = length($json);
+    while ($written_bytes < $bytes_to_write) {
+        $written_bytes += _syswrite($to_fd, $json, $bytes_to_write - 
$written_bytes, $written_bytes);
+        if ($!) {
+            die('myjsonrpc: remote end terminated connection, stopping') if 
!DEBUG_JSON && $! =~ qr/Broken pipe/;
+            confess sprintf "syswrite failed: err: '%s'; written_bytes: %d/%d; 
JSON: '%s'", $!, $written_bytes, $bytes_to_write, $json;
+        }
     }
     return $cmdcopy{json_cmd_token};
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/ppmclibs/tinycv_impl.cc 
new/os-autoinst-5.1745266261.8745de3/ppmclibs/tinycv_impl.cc
--- old/os-autoinst-5.1743091574.1f9ae10/ppmclibs/tinycv_impl.cc        
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/ppmclibs/tinycv_impl.cc        
2025-04-21 22:11:01.000000000 +0200
@@ -810,6 +810,12 @@
     size_t offset = 0;
     int orig_w = w;
     int orig_x = x;
+    long max_x = max(x + w, image_xres(a));
+    long max_y = max(y + h, image_yres(a));
+    if ((image_xres(a) < max_x) || (image_yres(a) < max_y)) {
+        /* If the current image is too small, create a new, bigger one */
+        a->img = Mat::zeros(max_y, max_x, a->img.type());
+    }
     while (h > 0) {
         w = orig_w;
         x = orig_x;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/script/imgsearch 
new/os-autoinst-5.1745266261.8745de3/script/imgsearch
--- old/os-autoinst-5.1743091574.1f9ae10/script/imgsearch       2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/script/imgsearch       2025-04-21 
22:11:01.000000000 +0200
@@ -14,8 +14,8 @@
 use needle;
 
 # define a basic needle package; normally `needle` should inherit from this 
package
-{
-    package basic_needle;    # uncoverable statement
+
+package basic_needle {    # uncoverable statement
     use base 'needle';
     use Mojo::File qw(path);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/script/os-autoinst-generate-needle-preview 
new/os-autoinst-5.1745266261.8745de3/script/os-autoinst-generate-needle-preview
--- 
old/os-autoinst-5.1743091574.1f9ae10/script/os-autoinst-generate-needle-preview 
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/os-autoinst-5.1745266261.8745de3/script/os-autoinst-generate-needle-preview 
    2025-04-21 22:11:01.000000000 +0200
@@ -0,0 +1,133 @@
+#!/usr/bin/perl -w
+# Copyright Roland Clobus <rclo...@rclobus.nl>
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+
+=head1 os-autoinst-generate-needle-preview
+
+os-autoinst-generate-needle-preview - generate an .svg file with the needle 
information as an overlay
+
+=head1 SYNOPSIS
+
+Use a list of files (using stdin or arguments):
+
+  ls -1 *.json | os-autoinst-generate-needle-preview -
+  os-autoinst-generate-needle-preview *.json
+
+Look for a specific tag:
+
+  grep "DESKTOP-gnome" -l *.json | os-autoinst-generate-needle-preview -
+
+=cut
+
+use Mojo::Base -strict, -signatures;
+use Getopt::Long;
+use Mojo::JSON qw(decode_json);
+use Mojo::File qw(path);
+use Mojo::Util qw(url_escape);
+
+sub process_file ($filename) {
+    my $SVGFILE;
+
+    chomp $filename;
+    my $pp = Mojo::File->new($filename);
+    my $name = $pp->basename(".json");
+    printf "Working on %s\n", $name;
+    my $pngpath = path($pp->dirname, "${name}.png");
+    my $output = qx/file --brief "${pngpath}"/;
+    my ($width, $height) = $output =~ /^PNG image data, (\d+) x (\d+)/;
+    if (!$width or !$height) {
+        say 'E: Could not determine image size';
+        return 1;
+    }
+
+    my $data  = decode_json($pp->slurp);
+
+    open $SVGFILE, '>', path($pp->dirname, "${name}.svg");
+    select $SVGFILE;
+
+    my $URIname = url_escape(${name});
+    # The generated file should be identical to the svg file as saved with 
inkscape as 'Standard SVG'
+    printf <<~"EOM";
+       <?xml version="1.0" encoding="UTF-8" standalone="no"?>
+       <!-- Created with os-autoinst-generate-needle-preview -->
+
+       <svg
+          version="1.1"
+          id="svg1"
+          width="${width}"
+          height="${height}"
+          viewBox="0 0 ${width} ${height}"
+          xmlns:xlink="http://www.w3.org/1999/xlink";
+          xmlns="http://www.w3.org/2000/svg";
+          xmlns:svg="http://www.w3.org/2000/svg";>
+         <defs
+            id="defs1" />
+         <image
+            width="${width}"
+            height="${height}"
+            preserveAspectRatio="none"
+            xlink:href="${URIname}.png"
+            id="needle_bitmap"
+            x="0"
+            y="0" />
+       EOM
+    my $area_counter = 1;
+    foreach my $area (@{$data->{area}}) {
+        say '  <rect';
+        if ($area->{type} eq 'match') {
+            say '     
style="fill:#00ff00;fill-opacity:0.5;stroke:#008000;stroke-width:2;stroke-opacity:0.75"';
+        } elsif ($area->{type} eq 'exclude') {
+            say '     
style="fill:#ff0000;fill-opacity:0.5;stroke:#800000;stroke-width:2;stroke-opacity:0.75"';
+        } else {
+            say '     
style="fill:#000000;fill-opacity:0.5;stroke:#808080;stroke-width:2;stroke-opacity:0.75"';
+        }
+        printf "     id=\"rect%d\"\n", $area_counter;
+        printf "     width=\"%d\"\n",  $area->{width};
+        printf "     height=\"%d\"\n", $area->{height};
+        printf "     x=\"%d\"\n",      $area->{xpos};
+        printf "     y=\"%d\" />\n",   $area->{ypos};
+        if ($area->{click_point}) {
+            say '  <circle';
+            say '     
style="fill:#ffffff;fill-opacity:0.5;stroke:#ffffff;stroke-width:2;stroke-opacity:0.75"';
+            printf "     id=\"path%d\"\n", $area_counter;
+            printf "     cx=\"%f\"\n", $area->{xpos} + 
$area->{click_point}->{xpos};
+            printf "     cy=\"%f\"\n", $area->{ypos} + 
$area->{click_point}->{ypos};
+            say '     r="10" />';
+        }
+        $area_counter++;
+    }
+    print <<~"EOM";
+       </svg>
+       EOM
+    select STDOUT;
+    close $SVGFILE;
+    return 0;
+}
+
+Getopt::Long::Configure("no_ignore_case");
+
+my %options;
+
+sub usage ($r)
+{
+    require Pod::Usage;
+    Pod::Usage::pod2usage($r)
+}
+
+GetOptions(\%options, 'help|h|?') or usage(1);
+usage(0) if $options{help};
+usage(1) unless @ARGV;
+
+my $has_error = 0;
+if ($ARGV[0] eq '-') {
+    # Read a list of files to process from stdin
+    while (<STDIN>) {
+        $has_error |= process_file $_;
+    }
+} else {
+    for (@ARGV) {
+        $has_error |= process_file $_;
+    }
+}
+exit $has_error;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/script/os-autoinst-openvswitch 
new/os-autoinst-5.1745266261.8745de3/script/os-autoinst-openvswitch
--- old/os-autoinst-5.1743091574.1f9ae10/script/os-autoinst-openvswitch 
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/script/os-autoinst-openvswitch 
2025-04-21 22:11:01.000000000 +0200
@@ -183,6 +183,7 @@
 sub _set_ip ($tap) { system('ip', 'link', 'set', $tap, 'up') }
 
 dbus_method("set_vlan", ["string", "uint32"], ["int32", "string"]);
+
 sub set_vlan ($self, $tap, $vlan) {
     my $return_output;
     my $return_code = 1;
@@ -214,6 +215,7 @@
 }
 
 dbus_method("unset_vlan", ["string", "uint32"], ["int32", "string"]);
+
 sub unset_vlan ($self, $tap, $vlan) {
     my $return_output;
     my $return_code = 1;
@@ -239,6 +241,7 @@
 sub _ovs_show () { _cmd('ovs-vsctl', 'show') }
 
 dbus_method("show", [], ["int32", "string"]);
+
 sub show ($self) {
     my ($return_code, undef, $ovs_vsctl_output) = _ovs_show;
     return $return_code, $ovs_vsctl_output;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/t/08-autotest.t 
new/os-autoinst-5.1745266261.8745de3/t/08-autotest.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/08-autotest.t        2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/08-autotest.t        2025-04-21 
22:11:01.000000000 +0200
@@ -37,6 +37,7 @@
 my @reset_consoles;
 my @selected_consoles;
 sub fake_send ($target, $msg) { push @sent, $msg }
+
 sub fake_read ($fd, $cmd_token = undef) {
     my $lcmd = $sent[-1];
     my $cmd = $lcmd->{cmd};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/t/12-bmwqemu.t 
new/os-autoinst-5.1745266261.8745de3/t/12-bmwqemu.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/12-bmwqemu.t 2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/12-bmwqemu.t 2025-04-21 
22:11:01.000000000 +0200
@@ -42,6 +42,7 @@
 
 subtest 'log_call' => sub {
     require bmwqemu;
+
     sub log_call_test {
         bmwqemu::log_call(foo => "bar\tbaz\rboo\n");
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/t/14-isotovideo.t 
new/os-autoinst-5.1745266261.8745de3/t/14-isotovideo.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/14-isotovideo.t      2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/14-isotovideo.t      2025-04-21 
22:11:01.000000000 +0200
@@ -294,8 +294,8 @@
 
 
 # mock backend/driver
-{
-    package FakeBackendDriver;    # uncoverable statement
+package FakeBackendDriver {    # uncoverable statement
+
     sub new ($class, $name) {
         my $self = bless({class => $class}, $class);
         require "backend/$name.pm";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/t/17-basetest.t 
new/os-autoinst-5.1745266261.8745de3/t/17-basetest.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/17-basetest.t        2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/17-basetest.t        2025-04-21 
22:11:01.000000000 +0200
@@ -43,6 +43,7 @@
 my $suppress_match;
 my @selected_consoles;
 sub fake_send_json ($to_fd, $cmd) { push(@$cmds, $cmd) }
+
 sub fake_read_json ($fd) {
     my $lcmd = $cmds->[-1];
     my $cmd = $lcmd->{cmd};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/t/18-qemu-options.t 
new/os-autoinst-5.1745266261.8745de3/t/18-qemu-options.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/18-qemu-options.t    2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/18-qemu-options.t    2025-04-21 
22:11:01.000000000 +0200
@@ -41,6 +41,7 @@
 my $vars_json = path('vars.json');
 my $log_file = path('autoinst-log.txt');
 my $log = '';
+
 sub run_isotovideo (@args) {
     $vars_json->spew(encode_json({@common_options, @args}));
     ok system("cd $toplevel_dir && perl $toplevel_dir/isotovideo --workdir 
$pool_dir -d qemu_disable_snapshots=1 2>&1 | tee $pool_dir/autoinst-log.txt") 
== 0, 'zero exit status';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/t/19-isotovideo-command-processing.t 
new/os-autoinst-5.1745266261.8745de3/t/19-isotovideo-command-processing.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/19-isotovideo-command-processing.t   
2025-03-27 17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/19-isotovideo-command-processing.t   
2025-04-21 22:11:01.000000000 +0200
@@ -41,17 +41,17 @@
 });
 
 # mock bmwqemu/backend
-{
-    package FakeBackend;    # uncoverable statement
+package FakeBackend {    # uncoverable statement
     sub new ($class) { bless({messages => []}, $class) }
+
     sub _send_json ($self, $cmd) {
         push(@{$self->{messages}}, $cmd);
         return $cmd->{cmd} eq 'is_shutdown' ? 'down' : {tags => [qw(some fake 
tags)]};
     }
     sub stop { die "faking stop\n" }
 }
-{
-    package bmwqemu;
+
+package bmwqemu {
     our $backend = FakeBackend->new();
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/t/24-myjsonrpc-debug.t 
new/os-autoinst-5.1745266261.8745de3/t/24-myjsonrpc-debug.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/24-myjsonrpc-debug.t 2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/24-myjsonrpc-debug.t 2025-04-21 
22:11:01.000000000 +0200
@@ -10,6 +10,7 @@
 use lib "$Bin/../external/os-autoinst-common/lib";
 use OpenQA::Test::TimeLimit '5';
 use Socket;
+
 BEGIN {
     $ENV{PERL_MYJSONRPC_DEBUG} = 1;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/t/24-myjsonrpc.t 
new/os-autoinst-5.1745266261.8745de3/t/24-myjsonrpc.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/24-myjsonrpc.t       2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/24-myjsonrpc.t       2025-04-21 
22:11:01.000000000 +0200
@@ -62,7 +62,7 @@
 
 subtest 'send_json dies when buffer is empty and pipe is broken' => sub {
     my $myjsonrpc_mock = Test::MockModule->new('myjsonrpc');
-    $myjsonrpc_mock->redefine(_syswrite => sub ($to_fd, $json) { 0 });
+    $myjsonrpc_mock->redefine(_syswrite => sub ($to_fd, $json, $len, $offset) 
{ 0 });
     dies_ok { myjsonrpc::send_json($child, $send1) } 'myjsonrpc: remote end 
terminated connection, stopping';
 };
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/t/27-consoles-vmware.t 
new/os-autoinst-5.1745266261.8745de3/t/27-consoles-vmware.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/27-consoles-vmware.t 2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/27-consoles-vmware.t 2025-04-21 
22:11:01.000000000 +0200
@@ -129,20 +129,20 @@
 
 subtest 'turning WebSocket into normal socket via dewebsockify' => sub {
     # define simple WebSocket server for testing
-    {
-        package TestWebSocketApp;    # uncoverable statement
+    package TestWebSocketApp {    # uncoverable statement
         use Mojo::Base 'Mojolicious', -signatures;
         has received_data => '';
+
         sub startup ($self) {
             $self->routes->websocket('/test')->to('test#start_ws');
             $self->routes->any('*')->to('test#fallback');
         }
         sub received_everything ($self) { length $self->received_data >= 
length 'message sent from raw socket' }
     }
-    {
-        # uncoverable statement count:2
-        package TestWebSocketApp::Controller::Test;
+    # uncoverable statement count:2
+    package TestWebSocketApp::Controller::Test {
         use Mojo::Base 'Mojolicious::Controller', -signatures;
+
         sub start_ws ($self) {
             my $sent_everything;
             $self->send({binary => 'binary sent from WebSocket'}, sub {
@@ -158,6 +158,7 @@
                 });
             $self->on(finish => sub ($ws, $code, $reason) { 
$self->ua->ioloop->stop });
         }
+
         sub fallback ($self) {
             Test::Most::note 'start replying HTTP response';
             $self->render(text => 'fallback', status => 404);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/t/39-dewebsockify.t 
new/os-autoinst-5.1745266261.8745de3/t/39-dewebsockify.t
--- old/os-autoinst-5.1743091574.1f9ae10/t/39-dewebsockify.t    2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/t/39-dewebsockify.t    2025-04-21 
22:11:01.000000000 +0200
@@ -54,6 +54,7 @@
 });
 
 {
+
     package MockTxGeneric;    # uncoverable statement
     use Test::Most;
     use Mojo::Base -strict, -signatures;
@@ -62,6 +63,7 @@
     sub max_websocket_size { }
     sub error { }
     sub req { bless {}, 'MockTxGenericReq' }
+
     sub on ($self, $event, $cb) {
         if ($event eq 'text') { $main::ws_on_text = $cb }
         elsif ($event eq 'binary') { $main::ws_on_binary = $cb }
@@ -95,6 +97,7 @@
 
     package MockTxFailWithCode;
     sub is_websocket { 0 }
+
     sub error {
         return {code => 403, message => 'Forbidden'};
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/t/41-os-autoinst-generate-needle-preview.t 
new/os-autoinst-5.1745266261.8745de3/t/41-os-autoinst-generate-needle-preview.t
--- 
old/os-autoinst-5.1743091574.1f9ae10/t/41-os-autoinst-generate-needle-preview.t 
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/os-autoinst-5.1745266261.8745de3/t/41-os-autoinst-generate-needle-preview.t 
    2025-04-21 22:11:01.000000000 +0200
@@ -0,0 +1,33 @@
+#!/usr/bin/env perl
+# Copyright Roland Clobus <rclo...@rclobus.nl>
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+use Test::Most;
+use Test::Warnings ':report_warnings';
+use Mojo::Base -strict, -signatures;
+use File::Compare qw(compare);
+use Mojo::File qw(path tempdir);
+
+use FindBin '$Bin';
+use lib "$FindBin::Bin/lib", "$Bin/../external/os-autoinst-common/lib";
+use OpenQA::Test::TimeLimit '5';
+
+sub check_os_autoinst_generate_needle_preview_default_needle ($use_stdin) {
+    my $dir = tempdir("$FindBin::Script-XXXX", TMPDIR => 1, CLEANUP => 1);
+    my $needle = "os-autoinst-generate-needle-preview";
+    path("$Bin/data/$needle.json")->copy_to("$dir/$needle.json");
+    path("$Bin/data/$needle.png")->copy_to("$dir/$needle.png");
+    if ($use_stdin) {
+        system("ls -1 $dir/$needle.json | 
$Bin/../script/os-autoinst-generate-needle-preview -");
+    } else {
+        system("$Bin/../script/os-autoinst-generate-needle-preview 
$dir/$needle.json");
+    }
+    is $?, 0, 'Command executed without error code';
+    is compare("$dir/$needle.svg", "$Bin/data/$needle.ref.svg"), 0, 'Equal to 
reference';
+}
+
+check_os_autoinst_generate_needle_preview_default_needle(0);
+check_os_autoinst_generate_needle_preview_default_needle(1);
+is system("$Bin/../script/os-autoinst-generate-needle-preview 
file.does.not.exist.json"), 1 << 8, 'Basic error handling';
+
+done_testing;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/t/data/os-autoinst-generate-needle-preview.json
 
new/os-autoinst-5.1745266261.8745de3/t/data/os-autoinst-generate-needle-preview.json
--- 
old/os-autoinst-5.1743091574.1f9ae10/t/data/os-autoinst-generate-needle-preview.json
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/os-autoinst-5.1745266261.8745de3/t/data/os-autoinst-generate-needle-preview.json
        2025-04-21 22:11:01.000000000 +0200
@@ -0,0 +1,32 @@
+{
+    "area": [
+        {
+            "click_point": {
+                "xpos": 125,
+                "ypos": 25
+            },
+            "height": 100,
+            "type": "match",
+            "width": 200,
+            "xpos": 50,
+            "ypos": 150
+        },
+        {
+            "height": 50,
+            "type": "exclude",
+            "width": 100,
+            "xpos": 220,
+            "ypos": 170
+        },
+        {
+            "height": 120,
+            "type": "ocr",
+            "width": 200,
+            "xpos": 50,
+            "ypos": 300
+        }
+    ],
+    "tags": [
+        "DESKTOP-gnome"
+    ]
+}
\ No newline at end of file
Binary files 
old/os-autoinst-5.1743091574.1f9ae10/t/data/os-autoinst-generate-needle-preview.png
 and 
new/os-autoinst-5.1745266261.8745de3/t/data/os-autoinst-generate-needle-preview.png
 differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/os-autoinst-5.1743091574.1f9ae10/t/data/os-autoinst-generate-needle-preview.ref.svg
 
new/os-autoinst-5.1745266261.8745de3/t/data/os-autoinst-generate-needle-preview.ref.svg
--- 
old/os-autoinst-5.1743091574.1f9ae10/t/data/os-autoinst-generate-needle-preview.ref.svg
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/os-autoinst-5.1745266261.8745de3/t/data/os-autoinst-generate-needle-preview.ref.svg
     2025-04-21 22:11:01.000000000 +0200
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with os-autoinst-generate-needle-preview -->
+
+<svg
+   version="1.1"
+   id="svg1"
+   width="1024"
+   height="768"
+   viewBox="0 0 1024 768"
+   xmlns:xlink="http://www.w3.org/1999/xlink";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:svg="http://www.w3.org/2000/svg";>
+  <defs
+     id="defs1" />
+  <image
+     width="1024"
+     height="768"
+     preserveAspectRatio="none"
+     xlink:href="os-autoinst-generate-needle-preview.png"
+     id="needle_bitmap"
+     x="0"
+     y="0" />
+  <rect
+     
style="fill:#00ff00;fill-opacity:0.5;stroke:#008000;stroke-width:2;stroke-opacity:0.75"
+     id="rect1"
+     width="200"
+     height="100"
+     x="50"
+     y="150" />
+  <circle
+     
style="fill:#ffffff;fill-opacity:0.5;stroke:#ffffff;stroke-width:2;stroke-opacity:0.75"
+     id="path1"
+     cx="175.000000"
+     cy="175.000000"
+     r="10" />
+  <rect
+     
style="fill:#ff0000;fill-opacity:0.5;stroke:#800000;stroke-width:2;stroke-opacity:0.75"
+     id="rect2"
+     width="100"
+     height="50"
+     x="220"
+     y="170" />
+  <rect
+     
style="fill:#000000;fill-opacity:0.5;stroke:#808080;stroke-width:2;stroke-opacity:0.75"
+     id="rect3"
+     width="200"
+     height="120"
+     x="50"
+     y="300" />
+</svg>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/os-autoinst-5.1743091574.1f9ae10/testapi.pm 
new/os-autoinst-5.1745266261.8745de3/testapi.pm
--- old/os-autoinst-5.1743091574.1f9ae10/testapi.pm     2025-03-27 
17:06:14.000000000 +0100
+++ new/os-autoinst-5.1745266261.8745de3/testapi.pm     2025-04-21 
22:11:01.000000000 +0200
@@ -29,7 +29,7 @@
 require bmwqemu;
 use constant OPENQA_LIBPATH => '/usr/share/openqa/lib';
 
-our @EXPORT = qw($realname $username $password $serialdev %cmd %vars
+our @EXPORT = qw($realname $username $password $serialdev %cmd
 
   get_var get_required_var check_var set_var get_var_array check_var_array 
autoinst_url
 

++++++ os-autoinst.obsinfo ++++++
--- /var/tmp/diff_new_pack.2CysUD/_old  2025-04-22 17:30:57.097807058 +0200
+++ /var/tmp/diff_new_pack.2CysUD/_new  2025-04-22 17:30:57.101807226 +0200
@@ -1,5 +1,5 @@
 name: os-autoinst
-version: 5.1743091574.1f9ae10
-mtime: 1743091574
-commit: 1f9ae1034eb75bd1c38f62bde94a503854ee9574
+version: 5.1745266261.8745de3
+mtime: 1745266261
+commit: 8745de34ae590c390e7251f78fed3694de1ab3a0
 

Reply via email to