Hello community,

here is the log from the commit of package transactional-update for 
openSUSE:Leap:15.2 checked in at 2020-03-13 10:56:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/transactional-update (Old)
 and      /work/SRC/openSUSE:Leap:15.2/.transactional-update.new.3160 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "transactional-update"

Fri Mar 13 10:56:26 2020 rev:71 rq:782183 version:2.20.3

Changes:
--------
--- 
/work/SRC/openSUSE:Leap:15.2/transactional-update/transactional-update.changes  
    2020-01-15 16:24:54.184634462 +0100
+++ 
/work/SRC/openSUSE:Leap:15.2/.transactional-update.new.3160/transactional-update.changes
    2020-03-13 10:56:31.864398568 +0100
@@ -1,0 +2,65 @@
+Tue Mar  3 16:34:26 UTC 2020 - Ignaz Forster <[email protected]>
+
+- Update to version 2.20.3
+  - Reintroduce compatibility with RPM < 4.15 for inclusion in
+    SLE / Leap 15.2
+  - Prepare for removal of /var/lib/alternatives [jsc#SLE-9101]
+
+-------------------------------------------------------------------
+Wed Feb 26 09:58:23 UTC 2020 - Ignaz Forster <[email protected]>
+
+- Update to version 2.20.2
+  - Use full names for zypper options [bsc#1164543]
+  - Ignore /var/lib/rpm in shadowed file output
+  - Optimize create-dirs-from-rpmdb
+
+-------------------------------------------------------------------
+Tue Jan  7 10:52:39 UTC 2020 - Ignaz Forster <[email protected]>
+
+- Update to version 2.20.1
+  - Add missing documentation about --continue option
+  - Avoid error message about missing fstab file on first snapshot creation.
+    [boo#1160213]
+
+-------------------------------------------------------------------
+Fri Nov  8 10:27:10 UTC 2019 - Ignaz Forster <[email protected]>
+
+- Update to version 2.20
+  - Add the option `--continue` to extend an existing snapshot. This can be
+    used to perform multiple operations before rebooting into the new state.
+    [gh#openSUSE/transactional-update#16]
+  - Make sure the dracut service to print warnings on /etc overlay conflicts
+    also runs in the pre-made images.
+  - Add "none" reboot method
+  - Remove conflicting overlay artifacts in case an existing overlay directory
+    will be reused
+
+-------------------------------------------------------------------
+Wed Sep 25 15:13:35 UTC 2019 - Ignaz Forster <[email protected]>
+
+- Update to version 2.17
+  - Provide network in shell on systems where resolv.conf is pointing to /run
+    directly [boo#1151081]
+  - Print new snapshot number at the end
+  - Always mount /root subvolume when using shell command to preserve history
+
+-------------------------------------------------------------------
+Mon Sep  9 19:36:59 UTC 2019 - Ignaz Forster <[email protected]>
+
+- Update to version 2.16
+  - Use default command if options, but no command was given [boo#1146116]
+  - Make sure only one process appears in `ps` output [boo#1111897]
+  - Move update check: If a new repository is added (and
+    ZYPPER_AUTO_IMPORT_KEYS is set) adding the new repository key won't fail
+    any more
+  - Avoid unnecessary snapshots / reboots by detecting zypper operations
+    without changes more reliably (e.g. when installing an already installed
+    package)
+  - Update the manpage accordingly
+  - Bugfixes:
+    - Ignore commented lines in fstab when checking for shadowed files
+    - Avoid warning when copying network config
+- Remove Perl dependency
+- Building documentation requires Python 3 now
+
+-------------------------------------------------------------------

Old:
----
  transactional-update-2.15.tar.gz

New:
----
  transactional-update-2.20.3.tar.gz

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

Other differences:
------------------
++++++ transactional-update.spec ++++++
--- /var/tmp/diff_new_pack.Sl8FLe/_old  2020-03-13 10:56:32.152398774 +0100
+++ /var/tmp/diff_new_pack.Sl8FLe/_new  2020-03-13 10:56:32.156398777 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package transactional-update
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           transactional-update
-Version:        2.15
+Version:        2.20.3
 Release:        0
 Summary:        Transactional Updates with btrfs and snapshots
 License:        GPL-2.0-or-later
@@ -31,15 +31,14 @@
 BuildRequires:  fdupes
 BuildRequires:  libzypp
 BuildRequires:  pkgconfig
-BuildRequires:  python-lxml
+BuildRequires:  python3-lxml
 BuildRequires:  rpm-devel
 BuildRequires:  suse-module-tools
 Requires:       attr
+Requires:       bc
 Requires:       logrotate
 Requires:       lsof
-Requires:       perl-HTML-Parser
 # psmisc is needed because of fuser
-Requires:       bc
 Requires:       psmisc
 Requires:       rsync
 Recommends:     rebootmgr

++++++ transactional-update-2.15.tar.gz -> transactional-update-2.20.3.tar.gz 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-2.15/NEWS 
new/transactional-update-2.20.3/NEWS
--- old/transactional-update-2.15/NEWS  2019-07-08 14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/NEWS        2020-03-03 17:27:07.000000000 
+0100
@@ -2,6 +2,51 @@
 
 Copyright (C) 2016-2019 Thorsten Kukuk et al.
 
+Version 2.20.3
+* Reintroduce compatibility with RPM < 4.15 for inclusion in SLE / Leap 15.2
+* Prepare for removal of /var/lib/alternatives [jsc#SLE-9810]
+
+Version 2.20.2
+* Use full names for zypper options [bsc#1164543]
+* Ignore /var/lib/rpm in shandowed file output
+* Optimize create-dirs-from-rpmdb
+
+Version 2.20.1
+* Add missing documentation about --continue option
+* Avoid error message about missing fstab file on first snapshot creation.
+  [boo#1160213]
+
+Version 2.20
+* Add the option `--continue` to extend an existing snapshot; this can be
+  used to perform multiple operations before rebooting into the new state
+* Make sure the dracut service to print warnings on /etc overlay conflicts
+  also runs in the pre-made images
+* Add "none" reboot method
+* Remove conflicting overlay artifacts in case an existing overlay directory
+  will be reused
+
+Version 2.17
+* Provide network in shell on systems where resolv.conf is pointing to /run
+  directly [boo#1151081]
+* Print new snapshot number at the end
+* Always mount /root subvolume when using shell command to preserve history
+
+Version 2.16
+* Use default command if options, but no command was given [boo#1146116]
+* Make sure only one process appears in `ps` output [boo#1111897]
+* Move update check: If a new repository is added (and
+  ZYPPER_AUTO_IMPORT_KEYS is set) adding the new repository key won't fail any
+  more
+* Avoid unnecessary snapshots / reboots by detecting zypper operations
+  without changes more reliably (e.g. when installing an already installed
+  package)
+* Update the manpage accordingly
+* Get rid of Perl dependency
+* Building documentation requires Python 3 now
+* Bugfixes:
+  * Ignore commented lines in fstab when checking for shadowed files
+  * Avoid warning when copying network config
+
 Version 2.15
 * Move description of interactiveness [boo#1132438]
 * Enable network during update [boo#1137890]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-2.15/configure.ac 
new/transactional-update-2.20.3/configure.ac
--- old/transactional-update-2.15/configure.ac  2019-07-08 14:57:13.000000000 
+0200
+++ new/transactional-update-2.20.3/configure.ac        2020-03-03 
17:27:07.000000000 +0100
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(transactional-update, 2.15)
+AC_INIT(transactional-update, 2.20.3)
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([sbin/transactional-update.in])
 AC_PREFIX_DEFAULT(/usr)
@@ -46,7 +46,8 @@
 dnl
 dnl Check for librpm
 dnl
-PKG_CHECK_MODULES([LIBRPM], [rpm])
+PKG_CHECK_MODULES([LIBRPM], [rpm >= 4.15], AC_DEFINE([HAVE_RPMDBCOOKIE]),
+       [PKG_CHECK_MODULES([LIBRPM], [rpm])])
 
 AC_ARG_WITH([doc],
        [AS_HELP_STRING([--with-doc], [Build documentation])], ,
@@ -67,7 +68,7 @@
                 [DocBook XSL Stylesheets], [], enable_man=no)
 
 m4_ifdef([AX_PYTHON_MODULE],
-       [AX_PYTHON_MODULE([lxml], , [python])],
+       [AX_PYTHON_MODULE([lxml])],
        [m4_warn([unsupported], [Missing macro AX_PYTHON_MODULE: please install
          autoconf-archive to enable Python module checks.])])
 AS_IF([test "${HAVE_PYMOD_LXML}" != "yes"], enable_man=no)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-2.15/doc/transactional-update.xml 
new/transactional-update-2.20.3/doc/transactional-update.xml
--- old/transactional-update-2.15/doc/transactional-update.xml  2019-07-08 
14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/doc/transactional-update.xml        
2020-03-03 17:27:07.000000000 +0100
@@ -16,7 +16,7 @@
         <email>[email protected]</email>
       </author>
     </authorgroup>
-    <releaseinfo>Version 0.2, 14. March 2019</releaseinfo>
+    <releaseinfo>Version 0.3, 12. September 2019</releaseinfo>
     <abstract>
       <para>
        This is the documentation for transactional-update and is intended for
@@ -27,6 +27,12 @@
        setting up and operating such a system and what a packager needs to
        know for creating compatible packages.
       </para>
+      <para>
+       For specific usage see the
+       <ulink 
url="https://kubic.opensuse.org/documentation/man-pages/transactional-update.8.html";>transactional-update
 man page</ulink>
+       or the
+       <ulink url="https://kubic.opensuse.org/documentation/man-pages/";>list 
of Kubic related commands</ulink>.
+      </para>
     </abstract>
   </bookinfo>
 
@@ -507,7 +513,10 @@
         <term><filename>/usr/etc/transactional-update.conf</filename></term>
         <listitem>
           <para>
-           TBD
+           This is the reference configuration file for
+           <command>transactional-update</command>, containing distribution
+           default values. This file should not be changed by the
+           administrator.
           </para>
         </listitem>
       </varlistentry>
@@ -515,7 +524,12 @@
         <term><filename>/etc/transactional-update.conf</filename></term>
         <listitem>
           <para>
-           TBD
+           To change the default configuration for
+           <command>transactional-update</command> copy or create this file
+           and change the options accordingly. See
+           <ulink 
url="https://kubic.opensuse.org/documentation/man-pages/transactional-update.conf.5.html";>transactional-update.conf(5)</ulink>
+           for a description of the configuration options. Values from this
+           file will overwride the distribution default values.
           </para>
         </listitem>
       </varlistentry>
@@ -523,7 +537,8 @@
         <term><filename>/var/lib/overlay/</filename></term>
         <listitem>
           <para>
-           TDB
+           See <xref linkend="tu-setup-etc" /> for an explanation of this
+           directory's contents.
           </para>
         </listitem>
       </varlistentry>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-2.15/dracut/module-setup.sh 
new/transactional-update-2.20.3/dracut/module-setup.sh
--- old/transactional-update-2.15/dracut/module-setup.sh        2019-07-08 
14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/dracut/module-setup.sh      2020-03-03 
17:27:07.000000000 +0100
@@ -1,16 +1,6 @@
 #!/bin/bash
 
 # called by dracut
-check() {
-    test -f /etc/fstab.sys || [[ -n $add_fstab  ||  -n $fstab_lines ]]
-}
-
-# called by dracut
-depends() {
-    echo fstab-sys
-}
-
-# called by dracut
 install() {
     inst_script "$moddir/transactional-update-etc-cleaner.sh" 
/bin/transactional-update-etc-cleaner
     inst_simple "$moddir/transactional-update-etc-cleaner.service" 
$systemdsystemunitdir/transactional-update-etc-cleaner.service
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-2.15/dracut/transactional-update-etc-cleaner.sh 
new/transactional-update-2.20.3/dracut/transactional-update-etc-cleaner.sh
--- old/transactional-update-2.15/dracut/transactional-update-etc-cleaner.sh    
2019-07-08 14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/dracut/transactional-update-etc-cleaner.sh  
2020-03-03 17:27:07.000000000 +0100
@@ -26,18 +26,23 @@
 warn_on_conflicting_files() {
   local dir="${1:-.}"
   local file
-  local snapdir="${PREV_ETC_OVERLAY}/${dir}"
+  local basedir="${PREV_ETC_OVERLAY}/${dir}"
+  local checkdir="${CURRENT_ETC_OVERLAY}/${dir}"
 
-  pushd "${CURRENT_ETC_OVERLAY}/${dir}" >/dev/null
+  echo "Checking for conflicts between ${PREV_ETC_OVERLAY}/${dir} and 
${CURRENT_ETC_OVERLAY}/${dir}..."
+
+  pushd "${checkdir}" >/dev/null
   for file in .[^.]* ..?* *; do
     # Filter unexpanded globs of "for" loop
     if [ ! -e "${file}" ]; then
       continue
     fi
 
-    if [ -e "${snapdir}/${file}" -a "${snapdir}/${file}" -nt 
"${CURRENT_ETC_OVERLAY}" ]; then
+    # Check whether a file present in a newer layer is also present in the
+    # original layer and has a timestamp from after branching the (first)
+    # snapshot.
+    if [ -e "${basedir}/${file}" -a "${basedir}/${file}" -nt 
"${NEW_OVERLAYS[-1]}" ]; then
       echo "WARNING: ${dir}/${file} or its contents changed in both old and 
new snapshot after snapshot creation!"
-      continue
     fi
 
     # Recursively process directories
@@ -56,7 +61,36 @@
   PREV_ETC_OVERLAY="${NEWROOT}/var/lib/overlay/${PREV_SNAPSHOT_ID}/etc"
 
   if [ "${CURRENT_SNAPSHOT_ID}" = "${EXPECTED_SNAPSHOT_ID}" -a -e 
"${CURRENT_ETC_OVERLAY}" ]; then
+    NEW_OVERLAYS=()
+    for option in `findmnt --noheadings --output OPTIONS /${NEWROOT}/etc | tr 
',' ' '`; do
+      case "${option%=*}" in
+        upperdir)
+          NEW_OVERLAYS[0]="${option#*=}"
+          ;;
+        lowerdir)
+          # If the previous overlay is not part of the stack just skip
+          if [[ $option != *"${PREV_ETC_OVERLAY}"* ]]; then
+            NEW_OVERLAYS=()
+            break
+          fi
+
+          i=1
+          for lowerdir in `echo ${option#*=} | tr ':' ' '`; do
+            if [ ${lowerdir} = ${PREV_ETC_OVERLAY} ]; then
+              break
+            fi
+            NEW_OVERLAYS[$i]="${lowerdir}"
+            ((i++))
+          done
+          ;;
+      esac
+    done
+
     rm "${TU_FLAGFILE}"
-    warn_on_conflicting_files
+
+    for overlay in "${NEW_OVERLAYS[@]}"; do
+      CURRENT_ETC_OVERLAY="${overlay}"
+      warn_on_conflicting_files
+    done
   fi
 fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-2.15/etc/transactional-update.conf 
new/transactional-update-2.20.3/etc/transactional-update.conf
--- old/transactional-update-2.15/etc/transactional-update.conf 2019-07-08 
14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/etc/transactional-update.conf       
2020-03-03 17:27:07.000000000 +0100
@@ -2,7 +2,7 @@
 # See transactional-update.conf(5) for details
 
 # Reboot method
-# Valid values: auto salt rebootmgr systemd kexec
+# Valid values: auto salt rebootmgr systemd kexec none
 #REBOOT_METHOD=auto
 
 # zypper update method
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/transactional-update-2.15/man/Makefile.am 
new/transactional-update-2.20.3/man/Makefile.am
--- old/transactional-update-2.15/man/Makefile.am       2019-07-08 
14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/man/Makefile.am     2020-03-03 
17:27:07.000000000 +0100
@@ -43,7 +43,7 @@
 endef
 
 transactional-update.index.xml: make-man-index.py $(XMLS)
-       python $(srcdir)/make-man-index.py $(srcdir)/$@ $(XMLS)
+       python3 $(srcdir)/make-man-index.py $(srcdir)/$@ $(XMLS)
 
 transactional-update.8: transactional-update.8.xml
        $(XSLTPROC) -o $(srcdir)/$@ --path $(srcdir) $(XSLTPROC_FLAGS_MAN) $<
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-2.15/man/transactional-update.8.xml 
new/transactional-update-2.20.3/man/transactional-update.8.xml
--- old/transactional-update-2.15/man/transactional-update.8.xml        
2019-07-08 14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/man/transactional-update.8.xml      
2020-03-03 17:27:07.000000000 +0100
@@ -79,16 +79,26 @@
 </para>
 <para>
 To achieve this <command>transactional-update</command> is using Btrfs'
-snapshot mechanism. Updates will be performed in a new snapshot of the root
-file system. The snapshot is created with
-<citerefentry 
project='snapper'><refentrytitle>snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-for the update
+snapshot mechanism, combined with the default distribution tools. Whenever an
+update of the root file system is going to be performed,
+<citerefentry 
project='snapper'><refentrytitle>snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+will create a new snapshot of the root file system first. This new snapshot is
+then used to perform the update, e.g. by calling
 <citerefentry 
project='zypper'><refentrytitle>zypper</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-is called with the <option>-R</option> option pointing to the new snapshot.
+with the <option>-R</option> option pointing to the new snapshot.
 If no errors occured the snapshot will be set as the new default snapshot and
 set as read-only. In case of errors the snapshot will be deleted again.
 </para>
 <para>
+By default the snapshot is always branched off from the current root file
+system, i.e. calling <command>transactional-update</command> multiple times
+without rebooting will create separate, independent snapshots, not containing
+the changes of the previous run. If multiple consecutive actions are to be
+executed, the <option>--continue</option> option can be used. This will still
+create a separate snapshot for each call, so it is possible to roll back to
+previous intermediate steps in case of errors.
+</para>
+<para>
 On <emphasis>read-only systems</emphasis> each snapshot will have a
 corresponding <filename class='directory'>/etc</filename> overlay located in
 <filename class='directory'>/var/lib/overlay</filename>. As configuration files
@@ -102,12 +112,11 @@
 removed at a later time (see the <option>cleanup</option> option).
 </para>
 <warning>
-If a file was changed both in the new snapshot (e.g. if a package installed a
-new version of the configuration file or used fillup-templates) and in the
-currently running system after creation of the new snapshot (e.g. if the
-administrator or configuration management software changed a file) only the
-version of the new snapshot will be visible. When rebooting into the new
-snapshot for the first time
+If a file in <filename class='directory'>/etc</filename> has been changed
+during the update and is <emphasis>also</emphasis> changed in the running
+system after the snapshot has been taken, then only the version of the new
+snapshot will be visible after a reboot.
+When booting into the new snapshot for the first time
 <filename>transactional-update-etc-cleaner.service</filename> will print a
 warning about such conflicts to the system log file.
 </warning>
@@ -134,10 +143,15 @@
 </refsect1>
 
 <refsect1 id='commands'><title>COMMANDS</title>
+<para>
+  If none of the following commands is given <option>up</option> will be
+  assumed.
+</para>
 <refsect2 id='general_commands'><title>General Commands</title>
 <para>
   General Commands can be used together in any combination; additionally they
   can be extended with one <link linkend='pkg_commands'>Package Command</link>.
+  The order of the General Commands doesn't matter.
 </para>
 <variablelist remap='TP'>
   <varlistentry>
@@ -197,12 +211,17 @@
     <term><option>reboot</option></term>
     <listitem>
       <para>
-       If a new snapshot with updates was created, the system should be
-       rebooted. This option will trigger the necessary reboot. If the
+       Trigger a reboot after updating the system.
+      </para>
+      <para>
+       Several different reboot methods are supported, configurable via the
+       <option>REBOOT_METHOD</option> configuration option in
+       
<citerefentry><refentrytitle>transactional-update.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+       By default
        
<citerefentry><refentrytitle>rebootmgrd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-       is running, <command>transactional-update</command> will tell the
-       daemon to reboot the system according to the configured policies. Else
-       <command>systemctl reboot</command> is called.
+       will be used to reboot the system according to the configured policies
+       if the service is running, otherwise <command>systemctl reboot</command>
+       will be called.
       </para>
     </listitem>
   </varlistentry>
@@ -236,9 +255,10 @@
   <option>--non-interactive</option> options.
 </para>
 <para>
-  Note that when using Package Commands non-interactively and combining them
-  with <link linkend='general_commands'>General Commands</link> the General
-  Commands will only be executed if the Package Command updated any packages.
+  To facilitate scripting Package Commands will exit early if no packages were
+  updated; if combined with
+  <link linkend='general_commands'>General Commands</link> those will not be
+  executed any more in that case.
 </para>
 <refsect3 id='ni_pkg_commands'><title>Non-interactive Package Commands</title>
 <variablelist>
@@ -386,6 +406,14 @@
     </listitem>
   </varlistentry>
   <varlistentry>
+    <term><option>--continue</option> 
<optional><replaceable>number</replaceable></optional></term>
+    <term><option>-c</option> 
<optional><replaceable>number</replaceable></optional></term>
+    <listitem>
+      <para>Use the given snapshot or, if no number is given, the current
+       default snapshot as a base for the next snapshot.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
     <term><option>--no-selfupdate</option></term>
     <listitem>
       <para>Skip checking for newer transactional-update versions.</para>
@@ -442,6 +470,7 @@
 <refsect1 id='see_also'><title>SEE ALSO</title>
 
<para><citerefentry><refentrytitle>transactional-update.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
 <citerefentry 
project='systemd'><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
-<citerefentry 
project='systemd'><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
+<citerefentry 
project='systemd'><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+<ulink 
url="https://kubic.opensuse.org/documentation/transactional-update-guide/transactional-update.html";>The
 Transactional Update Guide</ulink></para>
 </refsect1>
 </refentry>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-2.15/man/transactional-update.conf.5.xml 
new/transactional-update-2.20.3/man/transactional-update.conf.5.xml
--- old/transactional-update-2.15/man/transactional-update.conf.5.xml   
2019-07-08 14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/man/transactional-update.conf.5.xml 
2020-03-03 17:27:07.000000000 +0100
@@ -135,10 +135,29 @@
                 </para>
               </listitem>
             </varlistentry>
+            <varlistentry>
+              <term><literal>none</literal></term>
+              <listitem>
+                <para>
+                  Ignores any reboot request, the user has to reboot the
+                  machine manually or by other means.
+                </para>
+              </listitem>
+            </varlistentry>
           </variablelist>
        </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>UPDATE_METHOD</varname></term>
+        <listitem>
+          <para>
+           Specify the zypper update method to use. This value is used for
+           
<citerefentry><refentrytitle>transactional-update.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+          </para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>UPDATE_METHOD</varname></term>
         <listitem>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-2.15/sbin/create_dirs_from_rpmdb.c 
new/transactional-update-2.20.3/sbin/create_dirs_from_rpmdb.c
--- old/transactional-update-2.15/sbin/create_dirs_from_rpmdb.c 2019-07-08 
14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/sbin/create_dirs_from_rpmdb.c       
2020-03-03 17:27:07.000000000 +0100
@@ -21,6 +21,7 @@
 #include <config.h>
 #endif
 
+#include <fcntl.h>
 #include <sys/types.h>
 #include <pwd.h>
 #include <grp.h>
@@ -67,18 +68,29 @@
   uid_t user_id;
   gid_t group_id;
   time_t fmtime;
-  struct node *next;
 };
 
 struct node *dir_list = NULL;
+size_t dir_list_size = 0, dir_list_capacity = 0;
 
 /* A utility function to insert a node at the beginning of linked list */
 void
-insert_node (struct node** head_ref, const char *dirname, rpm_mode_t fmode,
+insert_node (const char *dirname, rpm_mode_t fmode,
             uid_t user_id, gid_t group_id, time_t fmtime)
 {
-  /* allocate node */
-  struct node* new_node = malloc(sizeof(struct node));
+  /* allocate space for the new node */
+  dir_list_size += 1;
+  size_t new_capacity = dir_list_capacity ? dir_list_capacity : 1;
+  while (new_capacity < dir_list_size)
+      new_capacity *= 2;
+
+  if (new_capacity != dir_list_capacity)
+    {
+      dir_list = realloc(dir_list, new_capacity * sizeof(struct node));
+      dir_list_capacity = new_capacity;
+    }
+
+  struct node *new_node = &dir_list[dir_list_size - 1];
 
   /* put in the data  */
   new_node->dirname  = strdup (dirname);
@@ -86,112 +98,12 @@
   new_node->user_id = user_id;
   new_node->group_id = group_id;
   new_node->fmtime = fmtime;
-
-  /* link the old list off the new node */
-  new_node->next = (*head_ref);
-
-  /* move the head to point to the new node */
-  (*head_ref) = new_node;
-}
-
-/* Returns the last node of the list */
-struct node *
-get_last_node (struct node *cur)
-{
-  while (cur != NULL && cur->next != NULL)
-    cur = cur->next;
-  return cur;
-}
-
-/* Partitions the list taking the last element as the pivot */
-struct node *
-partition(struct node *head, struct node *end,
-         struct node **newHead, struct node **newEnd)
-{
-  struct node *pivot = end;
-  struct node *prev = NULL, *cur = head, *tail = pivot;
-
-  /* During partition, both the head and end of the list might change
-     which is updated in the newHead and newEnd variables */
-  while (cur != pivot)
-    {
-      if (strcmp (cur->dirname, pivot->dirname) < 0)
-        {
-         /* First node that has a value less than the pivot - becomes
-            the new head */
-         if ((*newHead) == NULL)
-           (*newHead) = cur;
-
-         prev = cur;
-         cur = cur->next;
-        }
-      else  /* If cur node is greater than pivot */
-        {
-         /* Move cur node to next of tail, and change tail */
-         if (prev)
-           prev->next = cur->next;
-         struct node *tmp = cur->next;
-         cur->next = NULL;
-         tail->next = cur;
-         tail = cur;
-         cur = tmp;
-        }
-    }
-
-  /* If the pivot data is the smallest element in the current list,
-     pivot becomes the head */
-  if ((*newHead) == NULL)
-    (*newHead) = pivot;
-
-  (*newEnd) = tail;
-
-  return pivot;
-}
-
-
-struct node *
-quicksort_rec(struct node *head, struct node *end)
-{
-  struct node *newHead = NULL, *newEnd = NULL;
-  struct node *pivot;
-
-  if (!head || head == end)
-    return head;
-
-  /* Partition the list, newHead and newEnd will be updated
-     by the partition function */
-  pivot = partition(head, end, &newHead, &newEnd);
-
-  /* If pivot is the smallest element - no need to recur for
-     the left part. */
-  if (newHead != pivot)
-    {
-      /* Set the node before the pivot node as NULL */
-      struct node *tmp = newHead;
-      while (tmp->next != pivot)
-       tmp = tmp->next;
-      tmp->next = NULL;
-
-      newHead = quicksort_rec(newHead, tmp);
-
-      /* Change next of last node of the left half to pivot */
-      tmp = get_last_node(newHead);
-      tmp->next =  pivot;
-    }
-
-  /* Recur for the list after the pivot element */
-  pivot->next = quicksort_rec(pivot->next, newEnd);
-
-  return newHead;
 }
 
-/* The main function for quick sort. This is a wrapper over recursive
-   function quicksort_rec() */
-void
-quicksort (struct node **headRef)
+int
+nodecmp (const void *p1, const void *p2)
 {
-  (*headRef) = quicksort_rec(*headRef, get_last_node(*headRef));
-    return;
+    return strcmp(((const struct node*)p1)->dirname, ((const struct 
node*)p2)->dirname);
 }
 
 static char *
@@ -318,7 +230,7 @@
                  user_id = pwd->pw_uid;
                  group_id = grp->gr_gid;
 
-                 insert_node (&dir_list, fn, fmode, user_id, group_id, fmtime);
+                 insert_node (fn, fmode, user_id, group_id, fmtime);
                }
            }
        }
@@ -331,11 +243,11 @@
 }
 
 int
-create_dirs (struct node *node)
+create_dirs (struct node *node, size_t size)
 {
-  int rc = 0;
+  int rc = 0, i;
 
-  while (node != NULL)
+  for(i = 0; i < size; ++i, ++node)
     {
       struct timeval stamps[2] = {
        { .tv_sec = node->fmtime, .tv_usec = 0 },
@@ -349,7 +261,7 @@
        {
          fprintf (stderr, "Failed to create directory '%s': %m\n", 
node->dirname);
          rc = 1;
-         goto exit;
+         continue;
        }
 
       rc = chown (node->dirname, node->user_id, node->group_id);
@@ -359,17 +271,56 @@
          /* wrong permissions are bad, remove dir and continue */
          rmdir (node->dirname);
          rc = 1;
-         goto exit;
+         continue;
        }
       /* ignore errors here, time stamps are not critical */
       utimes (node->dirname, stamps);
-    exit:
-      node = node->next;
     }
 
   return rc;
 }
 
+int
+rpmCookieUnchanged (const char *rpmdb_cookie)
+{
+  int unchanged = 0, size = 0;
+  char *oldcookie = NULL;
+  FILE *cookiefile = fopen("/var/lib/create-dirs-from-rpmdb/cookie", "rb");
+
+  if (!cookiefile || fseek(cookiefile, 0, SEEK_END) != 0 || (size = 
ftell(cookiefile)) < 1 || fseek(cookiefile, 0, SEEK_SET) != 0)
+    goto end;
+
+  if (size == strlen(rpmdb_cookie))
+    {
+      oldcookie = malloc(size);
+      if (oldcookie && fread(oldcookie, size, 1, cookiefile) == 1)
+        unchanged = (strncmp(rpmdb_cookie, oldcookie, size) == 0);
+    }
+
+  end:
+
+  if (oldcookie)
+    free (oldcookie);
+
+  if (cookiefile)
+    fclose(cookiefile);
+
+  return unchanged;
+}
+
+void
+rpmCookieWrite (const char *rpmdb_cookie)
+{
+  mkdir("/var/lib", 0755);
+  mkdir("/var/lib/create-dirs-from-rpmdb", 0755);
+  FILE *cookief = fopen("/var/lib/create-dirs-from-rpmdb/cookie", "w");
+  if(!cookief)
+      return;
+
+  fwrite(rpmdb_cookie, strlen(rpmdb_cookie), 1, cookief);
+  fclose(cookief);
+}
+
 
 int
 main (int argc, char *argv[])
@@ -377,6 +328,7 @@
   Header h;
   rpmts ts = NULL;
   int ec = 0;
+  const char *rpmdb_cookie = NULL;
 
 
   while (1)
@@ -436,6 +388,20 @@
   ts = rpmtsCreate ();
   rpmtsSetRootDir (ts, rpmcliRootDir);
 
+#ifdef HAVE_RPMDBCOOKIE
+  rpmtsOpenDB (ts, O_RDONLY);
+  rpmdbOpenAll (rpmtsGetRdb (ts));
+  rpmdb_cookie = rpmdbCookie (rpmtsGetRdb (ts));
+  rpmtsCloseDB (ts);
+#endif
+  if (rpmdb_cookie && rpmCookieUnchanged(rpmdb_cookie))
+    {
+      if (verbose_flag)
+        puts("RPM cookie unchanged, not doing anything");
+      rpmtsFree (ts);
+      return 0;
+    }
+
   rpmdbMatchIterator mi = rpmtsInitIterator (ts, RPMDBI_PACKAGES, NULL, 0);
   if (mi == NULL)
     return 1;
@@ -451,13 +417,17 @@
   if (dir_list != NULL)
     {
       int rc;
-      quicksort (&dir_list);
-      if ((rc = create_dirs (dir_list)) != 0)
+      qsort (dir_list, dir_list_size, sizeof(struct node), nodecmp);
+      if ((rc = create_dirs (dir_list, dir_list_size)) != 0)
        ec = rc;
     }
 
   /* XXX missing: free list */
 
+  /* Can't do anything if this fails anyway. */
+  if (rpmdb_cookie)
+    rpmCookieWrite(rpmdb_cookie);
+
   rpmdbFreeIterator (mi);
   rpmtsFree (ts);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/transactional-update-2.15/sbin/transactional-update.in 
new/transactional-update-2.20.3/sbin/transactional-update.in
--- old/transactional-update-2.15/sbin/transactional-update.in  2019-07-08 
14:57:13.000000000 +0200
+++ new/transactional-update-2.20.3/sbin/transactional-update.in        
2020-03-03 17:27:07.000000000 +0100
@@ -55,7 +55,7 @@
 LOCKFILE="/var/run/transactional-update.pid"
 ZYPPER_AUTO_IMPORT_KEYS=0
 
ETC_OVERLAY_PATTERN='^[^[:space:]]\+[[:space:]]\+\/etc[[:space:]]\+overlay[[:space:]]\+\([^[:space:]]*,\|\)workdir=\/sysroot\/var\/lib\/overlay\/work-etc[,[:space:]]'
-NON_ROOTFS_WHITELIST=("/var/lib/systemd/migrated" "/var/run/zypp.pid")
+NON_ROOTFS_WHITELIST=("/var/lib/rpm" "/var/lib/systemd/migrated" 
"/var/run/zypp.pid")
 
 # Load config
 if [ -r ${SYSTEMCONFFILE} ]; then
@@ -72,6 +72,7 @@
 FORCE_NONINTERACTIVE=""
 SNAPSHOT_ID=""
 SNAPSHOT_DIR=""
+BASE_SNAPSHOT_ID=""
 MOUNT_DIR=""
 SNAPPER_NO_DBUS=""
 TMPFILE=""
@@ -83,7 +84,7 @@
        exec 4>&2
 fi
 # Log stderr to log file
-exec 2> >(tee -a "${LOGFILE}")
+exec 2> >(exec tee -a "${LOGFILE}")
 
 self_update() {
     if [ ${DO_SELF_UPDATE} == 0 ]; then
@@ -120,35 +121,36 @@
     echo "system."
     echo ""
     echo "General Commands:"
-    echo "cleanup                Mark unused snapshots for snapper removal"
-    echo "grub.cfg               Regenerate grub.cfg"
-    echo "bootloader             Reinstall the bootloader"
-    echo "initrd                 Regenerate initrd"
-    echo "kdump                  Regenerate kdump initrd"
-    echo "shell                  Open rw shell in new snapshot before exiting"
-    echo "reboot                 Reboot after update"
+    echo "cleanup                    Mark unused snapshots for snapper removal"
+    echo "grub.cfg                   Regenerate grub.cfg"
+    echo "bootloader                 Reinstall the bootloader"
+    echo "initrd                     Regenerate initrd"
+    echo "kdump                      Regenerate kdump initrd"
+    echo "shell                      Open rw shell in new snapshot before 
exiting"
+    echo "reboot                     Reboot after update"
     echo ""
     echo "Package Commands:"
     echo "Defaults: (i) interactive command; (n) non-interactive command"
-    echo "dup                    Call 'zypper dup' (n)"
-    echo "up                     Call 'zypper up' (n)"
-    echo "patch                  Call 'zypper patch' (n)"
-    echo "migration              Updates systems registered via SCC / SMT (i)"
-    echo "pkg install ...        Install individual packages (i)"
-    echo "pkg remove ...         Remove individual packages (i)"
-    echo "pkg update ...         Updates individual packages (i)"
+    echo "dup                        Call 'zypper dup' (n)"
+    echo "up                         Call 'zypper up' (n)"
+    echo "patch                      Call 'zypper patch' (n)"
+    echo "migration                  Updates systems registered via SCC / SMT 
(i)"
+    echo "pkg install ...            Install individual packages (i)"
+    echo "pkg remove ...             Remove individual packages (i)"
+    echo "pkg update ...             Updates individual packages (i)"
     echo ""
     echo "Standalone Commands:"
-    echo "rollback [<number>]    Set the current or given snapshot as default 
snapshot"
-    echo "rollback last          Set the last working snapshot as default 
snapshot"
+    echo "rollback [<number>]        Set the current or given snapshot as 
default snapshot"
+    echo "rollback last              Set the last working snapshot as default 
snapshot"
     echo ""
     echo "Options:"
-    echo "--interactive, -i      Use interactive mode for package command"
-    echo "--non-interactive, -n  Use non-interactive mode for package command"
-    echo "--no-selfupdate        Skip checking for newer version"
-    echo "--quiet                Don't print warnings and infos to stdout"
-    echo "--help, -h             Display this help and exit"
-    echo "--version              Display version and exit"
+    echo "--interactive, -i          Use interactive mode for package command"
+    echo "--non-interactive, -n      Use non-interactive mode for package 
command"
+    echo "--continue [<number>], -c  Use latest or given snapshot as base"
+    echo "--no-selfupdate            Skip checking for newer version"
+    echo "--quiet                    Don't print warnings and infos to stdout"
+    echo "--help, -h                 Display this help and exit"
+    echo "--version                  Display version and exit"
     exit $1
 }
 
@@ -451,7 +453,7 @@
     # Check for /etc overlay
     for fstab in "$1"/etc/fstab{,.sys}; do
        if [ -e "$fstab" ] ; then
-           overlay_options="`awk '$2 == "/etc" && $3 == "overlay" && $4 ~ 
"workdir=/sysroot/var/lib/overlay/work-etc" { print $4 }' "$fstab"`"
+           overlay_options="`findmnt --noheadings --types "overlay" --options 
"workdir=/sysroot/var/lib/overlay/work-etc" --output OPTIONS --tab-file 
"$fstab" /etc`"
            [ -n "${overlay_options}" ] && break
        fi
     done
@@ -494,12 +496,19 @@
     
fstab_oldest_active_snapshot="${fstab_oldest_active_snapshot:-/.snapshots/${CURRENT_SNAPSHOT_ID}/snapshot}"
 }
 
+# Replace all /sysroot prefixes from /etc fstab entry; for the overlays in /var
+# the prefix can simply be removed, while the lowest layer - the /etc directory
+# on the root file system - has to be replaced with the actual snapshot path,
+# as /etc overmounted with the current overlay already.
+parse_lowerdirs_for_mount() {
+    fstab_lowerdirs=("${fstab_lowerdirs[@]///sysroot\/var//var}")
+    echo ${fstab_lowerdirs[@]///sysroot/$1} | tr ' ' ':'
+}
+
 # Sync /etc mount contents to target directory
 sync_etc() {
-    local mount_opts overlay_id current_upper
+    local mount_opts overlay_id
 
-    get_etc_overlay_from /
-    current_upper="${fstab_upper}"
     get_etc_overlay_from "$1"
 
     # After fresh installations there's no overlay to sync yet
@@ -516,10 +525,7 @@
     if [ "${fstab_upper}" != "${current_upper}" ]; then
        mount_opts+="${fstab_upper#/sysroot}:"
     fi
-    # Replace all /sysroot prefixes; for /var it can simply be removed, the
-    # remaining root file system has to be replaced with the oldest snapshot
-    fstab_lowerdirs=("${fstab_lowerdirs[@]///sysroot\/var//var}")
-    mount_opts+="`echo ${fstab_lowerdirs[@]///sysroot/$1} | tr ' ' ':'`"
+    mount_opts+="`parse_lowerdirs_for_mount $1`"
     mount -t overlay overlay "${ETC_OVERLAY_DIR}" -o ${mount_opts}
     if [ $? -ne 0 ]; then
        log_error "ERROR: mount of old overlay stack from $1 failed!"
@@ -536,12 +542,6 @@
 
 ORIG_ARGS=("$@")
 
-# If no option is given, assume "up"
-if [ $# -eq 0 ]; then
-    ZYPPER_ARG="up"
-    TELEM_CLASS="update"
-fi
-
 while [ 1 ]; do
     if [ $# -eq 0 ]; then
        break
@@ -674,6 +674,16 @@
            FORCE_NONINTERACTIVE="${ZYPPER_NONINTERACTIVE}"
            shift
            ;;
+       -c|--continue)
+           # Check whether we got an optional snapshot number argument
+           if [[ $2 =~ ^[0-9]+$ ]]; then
+               BASE_SNAPSHOT_ID="$2"
+               shift
+           else
+               BASE_SNAPSHOT_ID="default"
+           fi
+           shift
+           ;;
        --no-selfupdate)
            DO_SELF_UPDATE=0
            shift
@@ -714,8 +724,11 @@
     esac
 done
 
-if [ $# -ne 0 ]; then
-    usage 1
+# If no commands were given, assume "up"
+if [ -z "${ZYPPER_ARG}" -a -z "${TELEM_CLASS}" -a "${REBOOT_AFTERWARDS}" -eq 0 
\
+       -a "${DO_REGISTRATION}" -eq 0 -a "${DO_CLEANUP}" -eq 0 ]; then
+    ZYPPER_ARG="up"
+    TELEM_CLASS="update"
 fi
 
 # Check if this is a self-updated transactional-update; if it isn't lock and
@@ -744,6 +757,14 @@
 
 telem_start
 
+SNAPPER_VERSION=`snapper --version | head -1 | cut -d ' ' -f 2`
+if [ -n "${BASE_SNAPSHOT_ID}" -a $(zypper --terse versioncmp $SNAPPER_VERSION 
0.8.4) -lt 0 ]; then
+    echo "ERROR: snapper >= 0.8.4 required for --continue option!"
+    log_info "transactional-update finished"
+    telem_finish 1
+    exit 1
+fi
+
 if [ "`stat -f -c %T /`" != "btrfs" ]; then
   log_error "ERROR: not using btrfs as root file system!"
   log_info "transactional-update finished"
@@ -761,7 +782,10 @@
 grep -q "[[:space:]]/var[[:space:]]" /proc/mounts
 if [ $? -eq 0 ]; then
     log_info "Separate /var detected."
-    DIR_TO_MOUNT="${DIR_TO_MOUNT} var/cache var/lib/alternatives"
+    DIR_TO_MOUNT="${DIR_TO_MOUNT} var/cache"
+    if [ -d /var/lib/alternatives ]; then
+       DIR_TO_MOUNT="${DIR_TO_MOUNT} var/lib/alternatives"
+    fi
     HAS_SEPARATE_VAR=1
 else
     grep -q var.cache /proc/mounts
@@ -778,7 +802,13 @@
 DEFAULT_SNAPSHOT_ID=`btrfs subvolume get-default / | sed -e 
's|.*.snapshots/\(.*\)/snapshot|\1|g'`
 RO_ROOT=`btrfs property get / ro | sed -e 's|ro=||'`
 
-get_etc_overlay_from "/.snapshots/${CURRENT_SNAPSHOT_ID}/snapshot"
+if [ -z "${BASE_SNAPSHOT_ID}" ]; then
+    BASE_SNAPSHOT_ID="${CURRENT_SNAPSHOT_ID}"
+elif [ "${BASE_SNAPSHOT_ID}" = "default" ]; then
+    BASE_SNAPSHOT_ID="${DEFAULT_SNAPSHOT_ID}"
+fi
+
+get_etc_overlay_from "/.snapshots/${BASE_SNAPSHOT_ID}/snapshot"
 if [ -n "$fstab_upper" ]; then
     log_info "/etc on overlayfs detected."
     ETC_IS_OVERLAY=1
@@ -920,54 +950,25 @@
     -o ${RUN_SHELL} -eq 1 -o ${REWRITE_BOOTLOADER} -eq 1 \
     -o ${DO_REGISTRATION} -eq 1 ]; then
 
-    # If the current snapshot and the default snapshot differ
-    # there have been changes that we are now discarding.
-    if [ "${DEFAULT_SNAPSHOT_ID}" -ne "${CURRENT_SNAPSHOT_ID}" ]; then
-       log_info "WARNING: Default snapshot differs from current snapshot."
-       log_info "WARNING: Any changes within the previous snapshot will be 
discarded!"
-    fi
-
-    # Check if there are updates at all. Don't check if we do
-    # a registration, as this can change the zypper result.
-    if [ -n "${ZYPPER_ARG}" -a -n "${ZYPPER_NONINTERACTIVE}" \
-         -a ${DO_REGISTRATION} -eq 0 -a ${DO_MIGRATION} -eq 0 ]; then
-
-       TMPFILE=`mktemp /tmp/transactional-update.XXXXXXXXXX`
-       zypper --xml ${ZYPPER_ARG} ${ZYPPER_NONINTERACTIVE} --dry-run 
"${ZYPPER_ARG_PKGS[@]}" > ${TMPFILE}
-       if [ $? -ne 0 ]; then
-           LOG_MESSAGES=`awk -v RS='<' -v FS='>' '{if ($1 ~ 
/^(message|description)/) print $2}' ${TMPFILE} | perl -MHTML::Entities -pe 
'decode_entities($_);'`
-           log_error "ERROR: Zypper failed with the following message(s):"
-           log_error "${LOG_MESSAGES}"
-           rm -f ${TMPFILE}
-           echo "Use '--interactive' for manual problem resolution."
-           quit 1
-       fi
-       PACKAGE_UPDATES=`grep "install-summary download-size" ${TMPFILE} | sed 
-e 's|.*install-summary download-size=\"\(.*\)\" space-usage-diff.*|\1|g'`
-       SIZE_OF_UPDATES=`grep "install-summary.*space-usage-diff" ${TMPFILE} | 
sed -e 's|.*install-summary.*space-usage-diff=\"\([^"]*\)\".*|\1|g'`
-       NUM_OF_UPDATES=`grep "install-summary.*packages-to-change" ${TMPFILE} | 
sed -e 's|.*install-summary.*packages-to-change=\"\([^"]*\)\".*|\1|g'`
-       rm -f ${TMPFILE}
-       
TELEM_PAYLOAD="${TELEM_PAYLOAD}\npackages=${NUM_OF_UPDATES}\ndownload_size=${PACKAGE_UPDATES}\nspace-usage=${SIZE_OF_UPDATES}"
-       if [ "${NUM_OF_UPDATES}" = "0" ] || [ -z "${NUM_OF_UPDATES}" -a 
"${PACKAGE_UPDATES}" = "0" -a "${SIZE_OF_UPDATES}" = "0" ]; then
-           log_info "zypper: nothing to update"
-           log_info "transactional-update finished"
-           if [ $USE_SALT_GRAINS -eq 1 ]; then
-               log_info "Updating salt grains"
-               if [ -f /etc/salt/grains ]; then
-                   # Reset tx_update_failed if it exists. Could have been set 
due to wrong
-                   # repository configuration or another temporary error 
before.
-                   sed -i -e 's|tx_update_failed:.*|tx_update_failed: false|g' 
/etc/salt/grains
-               fi
-           fi
-           telem_finish 0
-           exit 0
+    if [ "${DEFAULT_SNAPSHOT_ID}" -ne "${BASE_SNAPSHOT_ID}" ]; then
+       log_info "WARNING: You are creating a snapshot from a different base 
(${BASE_SNAPSHOT_ID}) than the"
+       log_info "         current default snapshot (${DEFAULT_SNAPSHOT_ID})."
+       if [ "${BASE_SNAPSHOT_ID}" -eq "${CURRENT_SNAPSHOT_ID}" ]; then
+           log_info "         If you want to continue a previous snapshot use 
the --continue"
+           log_info "         option, otherwise the previous changes will be 
discarded."
        fi
     fi
 
     # Create the working snapshot
-    SNAPSHOT_ID=`snapper create -p -u "transactional-update-in-progress=yes" 
-d "Snapshot Update of #${CURRENT_SNAPSHOT_ID}"`
+    snapper_args=(create --print-number --userdata 
"transactional-update-in-progress=yes")
+    if [ "${BASE_SNAPSHOT_ID}" -ne "${CURRENT_SNAPSHOT_ID}" ]; then
+       snapper_args+=(--from ${BASE_SNAPSHOT_ID})
+    fi
+    snapper_args+=(--description "Snapshot Update of #${BASE_SNAPSHOT_ID}")
+    SNAPSHOT_ID=`snapper "${snapper_args[@]}"`
     if [ $? -ne 0 ]; then
        SNAPPER_NO_DBUS="--no-dbus"
-       SNAPSHOT_ID=`snapper --no-dbus create -p -u 
"transactional-update-in-progress=yes" -d "Snapshot Update of 
#${CURRENT_SNAPSHOT_ID}"`
+       SNAPSHOT_ID=`snapper ${SNAPPER_NO_DBUS} "${snapper_args[@]}"`
        if [ $? -ne 0 ]; then
            log_error "ERROR: snapper create failed!"
            quit 1
@@ -986,20 +987,31 @@
     if [ ${ETC_IS_OVERLAY} -eq 1 ]; then
        # Create new /etc overlay for snapshot
        ETC_OVERLAY_DIR="/var/lib/overlay/${SNAPSHOT_ID}/etc"
+       ETC_OVERLAY_DIR_PREV="/var/lib/overlay/${BASE_SNAPSHOT_ID}/etc"
        ETC_OVERLAY_WORK_DIR="${ETC_OVERLAY_DIR}-work"
+
+       # If the user is calling `snapper delete` on the latest snapshot, then
+       # the snapshot number will be reused; make sure to delete any artifacts
+       rm -f "${ETC_OVERLAY_DIR}"
+
        mkdir -p "${ETC_OVERLAY_DIR}" "${ETC_OVERLAY_WORK_DIR}"
 
+       get_etc_overlay_from /
+       current_upper="${fstab_upper}"
+
        # Copy the contents of oldest /etc layer into snapshot
        sync_etc "${fstab_oldest_active_snapshot}" "${SNAPSHOT_DIR}"
-       get_etc_overlay_from "/.snapshots/${CURRENT_SNAPSHOT_ID}/snapshot"
+       get_etc_overlay_from "/.snapshots/${BASE_SNAPSHOT_ID}/snapshot"
 
        # Special handling /etc/fstab{.sys}: dracut needs the *current* version
        # of the files in the snapshot, as the overlay is not yet mounted
        # during early boot - in fact the files are required to be able to
        # mount the overlays
-       cp /etc/fstab "${SNAPSHOT_DIR}/etc"
-       if [ -e /etc/fstab.sys ]; then
-           cp -a /etc/fstab.sys "${SNAPSHOT_DIR}/etc"
+       if [ -e "${ETC_OVERLAY_DIR_PREV}/fstab" ]; then
+           cp "${ETC_OVERLAY_DIR_PREV}/fstab" "${SNAPSHOT_DIR}/etc"
+       fi
+       if [ -e "${ETC_OVERLAY_DIR_PREV}/fstab.sys" ]; then
+           cp -a "${ETC_OVERLAY_DIR_PREV}/fstab.sys" "${SNAPSHOT_DIR}/etc"
        fi
 
        # Migrate fstab.sys' /var and overlay entries to regular fstab
@@ -1059,13 +1071,11 @@
         rm -f ${SNAPSHOT_DIR}/var/update_snapshot.test
     fi
 
-    if [ ${RO_ROOT} == "true" ]; then
-       if [ ${RUN_SHELL} -eq 1 ]; then
-           DIR_TO_MOUNT="${DIR_TO_MOUNT} root"
-       fi
-       if [ -d /boot/writable ]; then
-           DIR_TO_MOUNT="${DIR_TO_MOUNT} /boot/writable"
-       fi
+    if [ ${RUN_SHELL} -eq 1 ]; then
+       DIR_TO_MOUNT="${DIR_TO_MOUNT} root"
+    fi
+    if [ -d /boot/writable ]; then
+       DIR_TO_MOUNT="${DIR_TO_MOUNT} /boot/writable"
     fi
 
     # Check which directories in /boot/grub2 need to be mounted,
@@ -1088,8 +1098,15 @@
         quit 1
     fi
     if [ ${ETC_IS_OVERLAY} -eq 1 ]; then
+       lowerdir="${fstab_upper///sysroot\/var//var}:"
+       lowerdir+="`parse_lowerdirs_for_mount 
"/.snapshots/${BASE_SNAPSHOT_ID}/snapshot"`"
+       # Check whether the current upper directory is part of the snapshot's 
lower
+       # directory stack; if so use reuse /etc directly instead, as mounting
+       # the same upper directory multiple times is not supported by overlayfs
+       lowerdir="${lowerdir/${current_upper#/sysroot}*/\/etc}"
+
        etc_opts="defaults,"
-       etc_opts+="lowerdir=/etc,"
+       etc_opts+="lowerdir=${lowerdir},"
        etc_opts+="upperdir=${ETC_OVERLAY_DIR},"
        etc_opts+="workdir=${ETC_OVERLAY_WORK_DIR}"
        mount -t overlay overlay ${SNAPSHOT_DIR}/etc -o ${etc_opts}
@@ -1138,9 +1155,13 @@
     fi
 
     # Copy network configuration into chroot
-    if [ -e /var/run/netconfig ]; then
-       mkdir -p ${SNAPSHOT_DIR}/var/run
-       cp -r /var/run/netconfig ${SNAPSHOT_DIR}/var/run/
+    # The links in /etc may either point to /var/run or /run, and the root file
+    # system snapshot may already contain the /var/run -> /run link or not.
+    if [ -e /run/netconfig ]; then
+       if [ ${HAS_SEPARATE_VAR} -eq 1 ]; then
+           ln -sf /run ${SNAPSHOT_DIR}/var/run
+       fi
+       cp -r /run/netconfig ${SNAPSHOT_DIR}/run/
     fi
 
     # Do we need to cleanup the /var/cache directory?
@@ -1164,26 +1185,34 @@
     if [ -n "${ZYPPER_ARG}" ]; then
 
        log_info "Calling zypper ${ZYPPER_ARG}"
-       if [ -n "${ZYPPER_NONINTERACTIVE}" ]; then
-           # In non-interactive mode, we redirect everything to a log file
-           if [ ${DO_MIGRATION} -eq 1 ]; then
-               # transactional-update migration
-               env DISABLE_RESTART_ON_UPDATE=yes zypper ${ZYPPER_ARG} --root 
${MOUNT_DIR} ${ZYPPER_NONINTERACTIVE} "${ZYPPER_ARG_PKGS[@]}" |& tee -a 
${LOGFILE}
-               RETVAL=${PIPESTATUS[0]}
-           else
-               env DISABLE_RESTART_ON_UPDATE=yes zypper -R ${MOUNT_DIR} 
${ZYPPER_ARG} ${ZYPPER_NONINTERACTIVE} "${ZYPPER_ARG_PKGS[@]}" |& tee -a 
${LOGFILE}
-               RETVAL=${PIPESTATUS[0]}
-           fi
+       if [ ${DO_MIGRATION} -eq 1 ]; then
+           # transactional-update migration
+           env DISABLE_RESTART_ON_UPDATE=yes zypper ${ZYPPER_ARG} --root 
${MOUNT_DIR} ${ZYPPER_NONINTERACTIVE} "${ZYPPER_ARG_PKGS[@]}" |& tee -a 
${LOGFILE}
+           RETVAL=${PIPESTATUS[0]}
        else
-           # in interactive mode, we don't redirect to a log file
-           if [ ${DO_MIGRATION} -eq 1 ]; then
-               # transactional-update migration
-               env DISABLE_RESTART_ON_UPDATE=yes zypper ${ZYPPER_ARG} --root 
${MOUNT_DIR} "${ZYPPER_ARG_PKGS[@]}"
-               RETVAL=$?
-           else
-               env DISABLE_RESTART_ON_UPDATE=yes zypper -R ${MOUNT_DIR} 
${ZYPPER_ARG} "${ZYPPER_ARG_PKGS[@]}"
-               RETVAL=$?
+           # Check if there are updates at all.
+           TMPFILE=`mktemp /tmp/transactional-update.XXXXXXXXXX`
+           zypper -R ${MOUNT_DIR} --xmlout ${ZYPPER_ARG} -y 
--auto-agree-with-product-licenses --dry-run "${ZYPPER_ARG_PKGS[@]}" > 
${TMPFILE}
+           PACKAGE_UPDATES=`grep "install-summary download-size" ${TMPFILE} | 
sed -e 's|.*install-summary download-size=\"\(.*\)\" space-usage-diff.*|\1|g'`
+           SIZE_OF_UPDATES=`grep "install-summary.*space-usage-diff" 
${TMPFILE} | sed -e 
's|.*install-summary.*space-usage-diff=\"\([^"]*\)\".*|\1|g'`
+           NUM_OF_UPDATES=`grep "install-summary.*packages-to-change" 
${TMPFILE} | sed -e 
's|.*install-summary.*packages-to-change=\"\([^"]*\)\".*|\1|g'`
+           rm -f ${TMPFILE}
+           
TELEM_PAYLOAD="${TELEM_PAYLOAD}\npackages=${NUM_OF_UPDATES}\ndownload_size=${PACKAGE_UPDATES}\nspace-usage=${SIZE_OF_UPDATES}"
+           if [ "${NUM_OF_UPDATES}" = "0" ] || [ -z "${NUM_OF_UPDATES}" -a 
"${PACKAGE_UPDATES}" = "0" -a "${SIZE_OF_UPDATES}" = "0" ]; then
+               log_info "zypper: nothing to update"
+               if [ $USE_SALT_GRAINS -eq 1 ]; then
+                   log_info "Updating salt grains"
+                   if [ -f /etc/salt/grains ]; then
+                       # Reset tx_update_failed if it exists. Could have been 
set due to wrong
+                       # repository configuration or another temporary error 
before.
+                       sed -i -e 's|tx_update_failed:.*|tx_update_failed: 
false|g' /etc/salt/grains
+                   fi
+               fi
+               quit 0
            fi
+
+           env DISABLE_RESTART_ON_UPDATE=yes zypper -R ${MOUNT_DIR} 
${ZYPPER_ARG} ${ZYPPER_NONINTERACTIVE} "${ZYPPER_ARG_PKGS[@]}" |& tee -a 
${LOGFILE}
+           RETVAL=${PIPESTATUS[0]}
        fi
        # in case of migration, we need to do a little bit more:
        if [ ${DO_MIGRATION} -eq 1 ]; then
@@ -1215,6 +1244,9 @@
            TELEM_PAYLOAD="${TELEM_PAYLOAD}\nnext_version=${VERSION_ID}"
        else
            log_error "ERROR: zypper ${ZYPPER_ARG} on ${MOUNT_DIR} failed with 
exit code ${RETVAL}!"
+           if [ -n "${ZYPPER_NONINTERACTIVE}" ]; then
+               echo "Use '--interactive' for manual problem resolution."
+           fi
            EXITCODE=1
        fi
     fi
@@ -1298,7 +1330,8 @@
     # visible in the actual system as they are shadowed by the real mount
     # points, so warn the user
     searchdirs=""
-    for mountdir in $(awk '$2 ~ "^/.*" { print $2 }' 
${SNAPSHOT_DIR}/etc/fstab); do
+    # Filter out commented lines and swap partition
+    for mountdir in $(awk '$1 !~ "^#.*" && $2 ~ "^/.*" { print $2 }' 
${SNAPSHOT_DIR}/etc/fstab); do
        # Filter out root fs and fstab entries which we bind mounted anyway
        if [[ ! $mountdir =~ ^(/|/etc|${DIR_TO_MOUNT// /|})$ ]]; then
            searchdirs+="${SNAPSHOT_DIR}${mountdir} "
@@ -1318,16 +1351,18 @@
            log_info "Warning: The following files were changed in the 
snapshot, but are shadowed by"
            log_info "other mounts and will not be visible to the system:"
            log_info "${filelist}"
-           log_info
        fi
     fi
 
     if [ ${EXITCODE} -ne 0 ]; then
        quit ${EXITCODE}
     elif [ $REBOOT_AFTERWARDS -eq 0 ]; then
+       echo
        echo "Please reboot your machine to activate the changes and avoid data 
loss."
        touch "${NEEDS_RESTARTING_FILE}"
     fi
+
+    log_info "New default snapshot is #${SNAPSHOT_ID} (${SNAPSHOT_DIR})."
 fi
 
 if [ ${EXITCODE} -eq 0 ]; then
@@ -1352,6 +1387,8 @@
            kexec)
                reboot_via_kexec
                ;;
+           none)
+               ;;
            *)
                log_info "Unsupported reboot method, falling back to 'auto'; 
please"
                log_info "check your configuration in ${CONFFILE}."


Reply via email to