Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package transactional-update for
openSUSE:Factory checked in at 2024-07-17 15:14:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/transactional-update (Old)
and /work/SRC/openSUSE:Factory/.transactional-update.new.17339 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "transactional-update"
Wed Jul 17 15:14:03 2024 rev:109 rq:1188045 version:4.7.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/transactional-update/transactional-update.changes
2024-05-09 12:07:29.417039699 +0200
+++
/work/SRC/openSUSE:Factory/.transactional-update.new.17339/transactional-update.changes
2024-07-17 15:14:34.728813590 +0200
@@ -1,0 +2,23 @@
+Tue Jul 16 18:12:53 UTC 2024 - Ignaz Forster <[email protected]>
+
+- It seems it's taking a longer time until the tests will be
+ adopted to the new reboot behavior. Disable soft-reboot for now
+ to unblock the regular transactional-update update.
+
+-------------------------------------------------------------------
+Thu Jul 4 15:22:40 UTC 2024 - Ignaz Forster <[email protected]>
+
+- Version 4.7.0
+ - Add plugin mechanism
+ It's now possible to hook into API functions with custom
+ plugins; see doc/tukit-plugins.md for details.
+ [gh#openSUSE/transactional-update#122]
+ - Fix missing libdir replacement for status command
+
+-------------------------------------------------------------------
+Fri Jun 14 10:06:31 UTC 2024 - Ignaz Forster <[email protected]>
+
+- Enable soft-reboot by default again as announced in
+ https://microos.opensuse.org/blog/2024-06-13-soft-reboot/
+
+-------------------------------------------------------------------
Old:
----
transactional-update-4.6.8.tar.gz
New:
----
transactional-update-4.7.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ transactional-update.spec ++++++
--- /var/tmp/diff_new_pack.4KoXAy/_old 2024-07-17 15:14:35.292834049 +0200
+++ /var/tmp/diff_new_pack.4KoXAy/_new 2024-07-17 15:14:35.296834193 +0200
@@ -26,7 +26,7 @@
%{!?_distconfdir: %global _distconfdir %{_prefix}%{_sysconfdir}}
Name: transactional-update
-Version: 4.6.8
+Version: 4.7.0
Release: 0
Summary: Transactional Updates with btrfs and snapshots
License: GPL-2.0-or-later AND LGPL-2.1-or-later
@@ -170,6 +170,9 @@
sed -i 's/^UPDATE_METHOD=.*/UPDATE_METHOD=up/' etc/transactional-update.conf
%endif
+# Enable soft-reboot by default
+sed -i 's/^REBOOT_ALLOW_SOFT_REBOOT=.*/REBOOT_ALLOW_SOFT_REBOOT=false/'
etc/tukit.conf
+
%install
%make_install
++++++ transactional-update-4.6.8.tar.gz -> transactional-update-4.7.0.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/NEWS
new/transactional-update-4.7.0/NEWS
--- old/transactional-update-4.6.8/NEWS 2024-05-07 14:12:47.000000000 +0200
+++ new/transactional-update-4.7.0/NEWS 2024-07-04 17:18:17.000000000 +0200
@@ -1,6 +1,13 @@
transactional-update NEWS -- history of user-visible changes.
-Copyright (C) 2016-2023 Thorsten Kukuk, Ignaz Forster et al.
+Copyright (C) 2016-2024 Thorsten Kukuk, Ignaz Forster et al.
+
+Version 4.7.0 (2024-07-04)
+* Add plugin mechanism
+ It's now possible to hook into API functions with custom plugins; see
+ doc/tukit-plugins.md for details.
+ [gh#openSUSE/transactional-update#122]
+* Fix missing libdir replacement for status command
Version 4.6.8 (2024-05-07)
* tukit: Properly handle overlay syncing failures: If the system would not be
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/configure.ac
new/transactional-update-4.7.0/configure.ac
--- old/transactional-update-4.6.8/configure.ac 2024-05-07 14:12:47.000000000
+0200
+++ new/transactional-update-4.7.0/configure.ac 2024-07-04 17:18:17.000000000
+0200
@@ -1,11 +1,11 @@
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(transactional-update, 4.6.8)
+AC_INIT(transactional-update, 4.7.0)
# Increase on any interface change and reset revision
-LIBTOOL_CURRENT=5
+LIBTOOL_CURRENT=6
# On interface change increase if backwards compatible, reset otherwise
-LIBTOOL_AGE=1
+LIBTOOL_AGE=2
# Increase on *any* C/C++ library code change, reset at interface change
-LIBTOOL_REVISION=3
+LIBTOOL_REVISION=0
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_FILES([tukit.pc])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/doc/tukit-plugins.md
new/transactional-update-4.7.0/doc/tukit-plugins.md
--- old/transactional-update-4.6.8/doc/tukit-plugins.md 1970-01-01
01:00:00.000000000 +0100
+++ new/transactional-update-4.7.0/doc/tukit-plugins.md 2024-07-04
17:18:17.000000000 +0200
@@ -0,0 +1,115 @@
+# Tukit plugins
+
+## Motivation
+
+Sometimes it is useful to inspect the content of a transaction in
+certain points. For example, before `transactional-update dup` we
+want to add new files into the system, and after the update we want to
+collect the list of new packages.
+
+With a plugin system we can provide scripts that can be executed
+before or after each action supported by `transactional-update`, like
+package installation, creation of new `initrd`, etc. This can work
+for most of the use cases, but there are certain tasks that cannot be
+done at this level.
+
+One example of those tasks is inspecting the `/run` directory after a
+full system upgrade to look for files that can signalize a condition,
+like the one that will trigger the `initrd` creation in a
+post-transaction scriptlet. The `/run` directory that is alive inside
+the new transaction is different from the one running in the host, but
+in both cases it is a `tmpfs` filesystem. This means that every time
+that it is unmounted we lost the information stored in there. Sadly,
+every time that `transactional-update` calls `tukit` to realize an
+action inside the snapshot, those directories are mounted and
+unmounted.
+
+The solution for this is to have the plugins at the `tukit` level.
+
+## Directories and shadowing
+
+The plugins can be installed in two different places:
+
+* `/usr/lib/tukit/plugins`: place for plugins that comes from packages
+* `/etc/tukit/plugins`: for user defined plugins
+
+The plugins in `/etc` can shadow the ones from `/usr` using the same
+name. For example, if the plugin `get_status` is in both places with
+the executable attribute, `tukit` will use the code from `/etc`,
+shadowing the one from the packages.
+
+One variation of shadowing is when the plugin in `/etc` is a soft link
+to `/dev/null`. This will be used as a mark to completely disable
+this plugin, and would not be called by `tukit`.
+
+The plugins in `/etc` will be called before the ones in `/usr` but the
+user should not depend on the calling order.
+
+## Stages
+
+The actions are based on the low-level API of libtukit, not of the
+user API level. This means that some verbs like `tukit execute <cmd>`
+will be presented as several of those low level actions: create
+snapshot, execute command, keep snapshot.
+
+Some actions will trigger a plugin call before and after the action
+itself, depending if it makes sense in the context of this action.
+
+The next table summarizes the action, the stage and different
+parameters sent to the plugin.
+
+| Action | Stage | Parameters | Notes |
+|----------|-------|-----------------------------------|-------|
+| init | -pre | | |
+| | -post | path, snapshot\_id | |
+| resume | -pre | snapshot\_id | |
+| | -post | path, snapshot\_id | |
+| execute | -pre | path, snapshot\_id, action params | |
+| | -post | path, snapshot\_id, action params | |
+| callExt | -pre | path, snapshot\_id, action params | [1] |
+| | -post | path, snapshot\_id, action params | |
+| finalize | -pre | path, snapshot\_id | |
+| | -post | snapshot\_id, [discarded] | [2] |
+| abort | -post | snapshot\_id | [3] |
+| keep | -pre | path, snapshot\_id | |
+| | -post | snapshot\_id | |
+| reboot | -pre | | |
+
+[1] The {} placeholder gets expanded in the arguments passed to the
+plugin
+
+[2] If the snapshot is discarded, the second parameter for the -post
+is "discarded"
+
+[3] abort-pre cannot be captured from the libtukit level
+
+
+## Example
+
+```bash
+#!/bin/bash
+
+exec_pre() {
+ local path="$1"; shift
+ local snapshot_id="$1"; shift
+ local cmd="$@"
+
+ # The live snapshot is in "$path", and the future closed snapshot in
+ # "/.snapshots/${snapshot_id}/snapshot
+
+ mkdir -p /var/lib/report
+ echo "${snapshot_id}: $cmd" >> /var/lib/report/all_commands
+}
+
+declare -A commands
+
+commands['execute-pre']=exec_pre
+commands['callExt-pre']=exec_pre
+
+cmd="$1"
+shift
+[ -n "$cmd" ] || cmd=help
+if [ "${#commands[$cmd]}" -gt 0 ]; then
+ ${commands[$cmd]} "$@"
+fi
+```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/lib/Makefile.am
new/transactional-update-4.7.0/lib/Makefile.am
--- old/transactional-update-4.6.8/lib/Makefile.am 2024-05-07
14:12:47.000000000 +0200
+++ new/transactional-update-4.7.0/lib/Makefile.am 2024-07-04
17:18:17.000000000 +0200
@@ -3,14 +3,14 @@
libtukit_la_SOURCES=Transaction.cpp \
SnapshotManager.cpp Snapshot/Snapper.cpp \
Mount.cpp Overlay.cpp Reboot.cpp Configuration.cpp \
- Util.cpp Supplement.cpp Bindings/CBindings.cpp
+ Util.cpp Supplement.cpp Plugins.cpp Bindings/CBindings.cpp
publicheadersdir=$(includedir)/tukit
publicheaders_HEADERS=Transaction.hpp \
SnapshotManager.hpp Reboot.hpp \
Bindings/libtukit.h
noinst_HEADERS=Snapshot/Snapper.hpp Snapshot.hpp \
Mount.hpp Overlay.hpp Log.hpp Configuration.hpp \
- Util.hpp Supplement.hpp Exceptions.hpp
+ Util.hpp Supplement.hpp Exceptions.hpp Plugins.hpp
libtukit_la_CPPFLAGS=-DPREFIX=\"$(prefix)\" -DCONFDIR=\"$(sysconfdir)\"
$(ECONF_CFLAGS) $(LIBMOUNT_CFLAGS) $(SELINUX_CFLAGS)
libtukit_la_LDFLAGS=$(ECONF_LIBS) $(LIBMOUNT_LIBS) $(SELINUX_LIBS) \
-version-info $(LIBTOOL_CURRENT):$(LIBTOOL_REVISION):$(LIBTOOL_AGE)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/lib/Plugins.cpp
new/transactional-update-4.7.0/lib/Plugins.cpp
--- old/transactional-update-4.6.8/lib/Plugins.cpp 1970-01-01
01:00:00.000000000 +0100
+++ new/transactional-update-4.7.0/lib/Plugins.cpp 2024-07-04
17:18:17.000000000 +0200
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* SPDX-FileCopyrightText: 2024 SUSE LLC */
+
+/* Plugin mechanism for tukit */
+
+#include "Exceptions.hpp"
+#include "Log.hpp"
+#include "Plugins.hpp"
+#include "Util.hpp"
+#include <set>
+#include <unistd.h>
+
+namespace TransactionalUpdate {
+
+using namespace std;
+
+Plugins::Plugins(TransactionalUpdate::Transaction* transaction):
transaction(transaction) {
+ set<string> plugins_set{};
+
+ const filesystem::path
plugins_dir{filesystem::path(CONFDIR)/"tukit"/"plugins"};
+ const filesystem::path
system_plugins_dir{filesystem::path(PREFIX)/"lib"/"tukit"/"plugins"};
+
+ for (auto d: {plugins_dir, system_plugins_dir}) {
+ if (!filesystem::exists(d))
+ continue;
+
+ for (auto const& dir_entry: filesystem::directory_iterator{d}) {
+ auto path = dir_entry.path();
+ auto filename = dir_entry.path().filename();
+
+ // Plugins can be shadowed, so a plugin in /etc can
+ // replace one from /usr/lib
+ if (plugins_set.count(filename) != 0)
+ continue;
+
+ // If is a symlink to /dev/null, ignore and shadow it
+ if (filesystem::is_symlink(path) && filesystem::read_symlink(path)
== "/dev/null") {
+ plugins_set.insert(filename);
+ continue;
+ }
+
+ // If the plugin is not executable, ignore it
+ if (!(filesystem::is_regular_file(path) && (access(path.c_str(),
X_OK) == 0)))
+ continue;
+
+ tulog.info("Found plugin ", path);
+ plugins.push_back(path);
+ plugins_set.insert(filename);
+ }
+ }
+}
+
+Plugins::~Plugins() {
+ plugins.clear();
+}
+
+void Plugins::run(string stage, string args) {
+ std::string output;
+
+ for (auto& p: plugins) {
+ std::string cmd = p.string() + " " + stage;
+ if (!args.empty())
+ cmd.append(" " + args);
+
+ try {
+ output = Util::exec(cmd);
+ if (!output.empty())
+ tulog.info("Output of plugin ", p, ": ", output);
+ } catch (const ExecutionException &e) {
+ // An error in the plugin should not discard the transaction
+ tulog.error("ERROR: Plugin ", p, " failed with ", e.what());
+ }
+ }
+}
+
+void Plugins::run(string stage, char* argv[]) {
+ std::string args;
+
+ if (transaction != nullptr)
+ args.append(transaction->getBindDir().string() + " " +
transaction->getSnapshot());
+
+ int i = 0;
+ while (argv != nullptr && argv[i]) {
+ args.append(" ");
+ args.append(argv[i++]);
+ }
+
+ run(stage, args);
+}
+
+} // namespace TransactionalUpdate
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/lib/Plugins.hpp
new/transactional-update-4.7.0/lib/Plugins.hpp
--- old/transactional-update-4.6.8/lib/Plugins.hpp 1970-01-01
01:00:00.000000000 +0100
+++ new/transactional-update-4.7.0/lib/Plugins.hpp 2024-07-04
17:18:17.000000000 +0200
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* SPDX-FileCopyrightText: 2024 SUSE LLC */
+
+/* Plugin mechanism for tukit */
+
+#ifndef T_U_PLUGINS_H
+#define T_U_PLUGINS_H
+
+#include "Transaction.hpp"
+#include <filesystem>
+#include <string>
+#include <vector>
+
+namespace TransactionalUpdate {
+
+class Plugins {
+public:
+ Plugins(TransactionalUpdate::Transaction* transaction);
+ virtual ~Plugins();
+ void run(std::string stage, std::string args);
+ void run(std::string stage, char* argv[]);
+protected:
+ TransactionalUpdate::Transaction* transaction;
+ std::vector<std::filesystem::path> plugins;
+};
+
+} // namespace TransactionalUpdate
+
+#endif // T_U_PLUGINS_H
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/lib/Reboot.cpp
new/transactional-update-4.7.0/lib/Reboot.cpp
--- old/transactional-update-4.6.8/lib/Reboot.cpp 2024-05-07
14:12:47.000000000 +0200
+++ new/transactional-update-4.7.0/lib/Reboot.cpp 2024-07-04
17:18:17.000000000 +0200
@@ -9,6 +9,7 @@
#include "Configuration.hpp"
#include "Exceptions.hpp"
#include "Log.hpp"
+#include "Plugins.hpp"
#include "Snapshot.hpp"
#include "SnapshotManager.hpp"
#include "Util.hpp"
@@ -77,6 +78,8 @@
}
void Reboot::reboot() {
+ TransactionalUpdate::Plugins plugins{nullptr};
+ plugins.run("reboot-pre", nullptr);
Util::exec(command);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/lib/Transaction.cpp
new/transactional-update-4.7.0/lib/Transaction.cpp
--- old/transactional-update-4.6.8/lib/Transaction.cpp 2024-05-07
14:12:47.000000000 +0200
+++ new/transactional-update-4.7.0/lib/Transaction.cpp 2024-07-04
17:18:17.000000000 +0200
@@ -12,6 +12,7 @@
#include "Log.hpp"
#include "Mount.hpp"
#include "Overlay.hpp"
+#include "Plugins.hpp"
#include "SnapshotManager.hpp"
#include "Snapshot.hpp"
#include "Supplement.hpp"
@@ -80,6 +81,8 @@
if (isInitialized() && !getSnapshot().empty() &&
fs::exists(getRoot())) {
tulog.info("Discarding snapshot ", pImpl->snapshot->getUid(), ".");
pImpl->snapshot->abort();
+ TransactionalUpdate::Plugins plugins{nullptr};
+ plugins.run("abort-post", pImpl->snapshot->getUid());
}
} catch (const std::exception &e) {
tulog.error("ERROR: ", e.what());
@@ -98,6 +101,10 @@
return pImpl->snapshot->getRoot();
}
+fs::path Transaction::getBindDir() {
+ return pImpl->bindDir;
+}
+
void Transaction::impl::snapMount() {
if (unshare(CLONE_NEWNS) < 0) {
throw std::runtime_error{"Creating new mount namespace failed: " +
std::string(strerror(errno))};
@@ -256,6 +263,9 @@
}
void Transaction::init(std::string base, std::optional<std::string>
description) {
+ TransactionalUpdate::Plugins plugins{nullptr};
+ plugins.run("init-pre", nullptr);
+
if (base == "active")
base = pImpl->snapshotMgr->getCurrent();
else if (base == "default")
@@ -291,9 +301,15 @@
// Flag file to indicate this snapshot was initialized with discard
flag
std::ofstream output(getRoot() / "discardIfNoChange");
}
+
+ TransactionalUpdate::Plugins plugins_with_transaction{this};
+ plugins_with_transaction.run("init-post", nullptr);
}
void Transaction::resume(std::string id) {
+ TransactionalUpdate::Plugins plugins{nullptr};
+ plugins.run("resume-pre", id);
+
pImpl->snapshot = pImpl->snapshotMgr->open(id);
if (! pImpl->snapshot->isInProgress()) {
pImpl->snapshot.reset();
@@ -304,6 +320,9 @@
if (fs::exists(getRoot() / "discardIfNoChange")) {
pImpl->discardIfNoChange = true;
}
+
+ TransactionalUpdate::Plugins plugins_with_transaction{this};
+ plugins_with_transaction.run("resume-post", nullptr);
}
void Transaction::setDiscardIfUnchanged(bool discard) {
@@ -452,7 +471,11 @@
}
int Transaction::execute(char* argv[], std::string* output) {
- return this->pImpl->runCommand(argv, true, output);
+ TransactionalUpdate::Plugins plugins{this};
+ plugins.run("execute-pre", argv);
+ int status = this->pImpl->runCommand(argv, true, output);
+ plugins.run("execute-post", argv);
+ return status;
}
int Transaction::callExt(char* argv[], std::string* output) {
@@ -466,7 +489,12 @@
s.replace(pos, from.size(), this->pImpl->bindDir);
argv[i] = strdup(s.c_str());
}
- return this->pImpl->runCommand(argv, false, output);
+
+ TransactionalUpdate::Plugins plugins{this};
+ plugins.run("callExt-pre", argv);
+ int status = this->pImpl->runCommand(argv, false, output);
+ plugins.run("callExt-post", argv);
+ return status;
}
void Transaction::sendSignal(int signal) {
@@ -478,6 +506,9 @@
}
void Transaction::finalize() {
+ TransactionalUpdate::Plugins plugins{this};
+ plugins.run("finalize-pre", nullptr);
+
sync();
if (pImpl->discardIfNoChange &&
((inotifyFd != 0 && pImpl->inotifyRead() == 0) ||
@@ -511,6 +542,8 @@
Util::exec("rsync --archive --inplace --xattrs --acls --exclude
'fstab' --delete --quiet '" + this->pImpl->bindDir.native() + "/etc/' " +
targetRoot.native() + "/etc");
}
+ TransactionalUpdate::Plugins plugins_without_transaction{nullptr};
+ plugins_without_transaction.run("finalize-post",
pImpl->snapshot->getUid() + " " + "discarded");
return;
}
if (fs::exists(getRoot() / "discardIfNoChange")) {
@@ -531,15 +564,26 @@
pImpl->snapshot->setDefault();
tulog.info("New default snapshot is #" + pImpl->snapshot->getUid() + " ("
+ std::string(pImpl->snapshot->getRoot()) + ").");
+ std::string id = pImpl->snapshot->getUid();
pImpl->snapshot.reset();
+
+ TransactionalUpdate::Plugins plugins_without_transaction{nullptr};
+ plugins_without_transaction.run("finalize-post", id);
}
void Transaction::keep() {
+ TransactionalUpdate::Plugins plugins{this};
+ plugins.run("keep-pre", nullptr);
+
sync();
if (fs::exists(pImpl->snapshot->getRoot() / "discardIfNoChange") &&
(inotifyFd != 0 && pImpl->inotifyRead() > 0)) {
tulog.debug("Snapshot was changed, removing discard flagfile.");
fs::remove(pImpl->snapshot->getRoot() / "discardIfNoChange");
}
pImpl->supplements.cleanup();
+ std::string id = pImpl->snapshot->getUid();
pImpl->snapshot.reset();
+
+ TransactionalUpdate::Plugins plugins_without_transaction{nullptr};
+ plugins_without_transaction.run("keep-post", id);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/lib/Transaction.hpp
new/transactional-update-4.7.0/lib/Transaction.hpp
--- old/transactional-update-4.6.8/lib/Transaction.hpp 2024-05-07
14:12:47.000000000 +0200
+++ new/transactional-update-4.7.0/lib/Transaction.hpp 2024-07-04
17:18:17.000000000 +0200
@@ -167,6 +167,10 @@
* root path as long as Transaction's destructor hasn't been called.
*/
std::filesystem::path getRoot();
+
+ friend class Plugins;
+protected:
+ std::filesystem::path getBindDir();
private:
class impl;
std::unique_ptr<impl> pImpl;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/sbin/Makefile.am
new/transactional-update-4.7.0/sbin/Makefile.am
--- old/transactional-update-4.6.8/sbin/Makefile.am 2024-05-07
14:12:47.000000000 +0200
+++ new/transactional-update-4.7.0/sbin/Makefile.am 2024-07-04
17:18:17.000000000 +0200
@@ -12,6 +12,7 @@
do_subst = sed -e 's,[@]sysconfdir[@],$(sysconfdir),g' \
-e 's,[@]prefix[@],$(prefix),g' \
+ -e 's,[@]libdir[@],$(libdir),g' \
-e 's,[@]VERSION[@],$(VERSION),g'
transactional-update: transactional-update.in Makefile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/transactional-update-4.6.8/tukit/main.cpp
new/transactional-update-4.7.0/tukit/main.cpp
--- old/transactional-update-4.6.8/tukit/main.cpp 2024-05-07
14:12:47.000000000 +0200
+++ new/transactional-update-4.7.0/tukit/main.cpp 2024-07-04
17:18:17.000000000 +0200
@@ -14,7 +14,7 @@
try {
TUKit ta{argc, argv};
} catch (int e) {
- return e;
+ return e;
} catch (const exception &e) {
cerr << "ERROR: " << e.what() << endl;
return 1;