From 3cd0a5313edbdb35e03041e606de3ae84f5ce790 Mon Sep 17 00:00:00 2001
From: Markus Raab <elektra@markus-raab.org>
Date: Tue, 19 Dec 2017 19:58:39 +0100
Subject: [PATCH] kdb-mount: experimental strategy feature

"--strategy unchanged" as discussed #1306
seems to be buggy:
e.g. if plugins add plugin config (like dump)
     parent keys disappear and it seems like
     the config was changed (although it was not)
---
 doc/help/elektra-merge-strategy.md |  6 ++++--
 src/tools/kdb/mount.cpp            | 29 ++++++++++++++++++++++++++++-
 src/tools/kdb/mount.hpp            |  2 +-
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/doc/help/elektra-merge-strategy.md b/doc/help/elektra-merge-strategy.md
index 2eb9c37c8ba..a7eff1cff3e 100644
--- a/doc/help/elektra-merge-strategy.md
+++ b/doc/help/elektra-merge-strategy.md
@@ -40,7 +40,9 @@ Currently the following strategies exist:
  * cut:
    Removes existing keys below the resultpath and replaces them with the merged keyset.
 
- * import:
+ * unchanged: (EXPERIMENTAL, only for kdb-mount)
+   Do not fail if the operation does not change anything.
+
+ * import: (DEPRECATED, avoid using it)
    Preserves existing keys in the resultpath if they do not exist in the merged keyset.
    If the key does exist in the merged keyset, it will be overwritten.
-   (avoid using it)
diff --git a/src/tools/kdb/mount.cpp b/src/tools/kdb/mount.cpp
index d301b18b6b5..6118e91aa36 100644
--- a/src/tools/kdb/mount.cpp
+++ b/src/tools/kdb/mount.cpp
@@ -14,6 +14,8 @@
 #include <cmdline.hpp>
 #include <mount.hpp>
 
+#include <keysetio.hpp>
+
 #include <fstream>
 #include <iostream>
 #include <iterator>
@@ -101,7 +103,9 @@ void MountCommand::buildBackend (Cmdline const & cl)
 		throw invalid_argument (mp + " is not a valid mountpoint");
 	}
 
-	if (cl.force)
+	KeySet dupMountConf = mountConf.dup ();
+
+	if (cl.force || cl.strategy != "preserve")
 	{
 		Key cutKey (Backends::mountpointsPath, KEY_END);
 		cutKey.addBaseName (mpk.getName ());
@@ -168,6 +172,29 @@ void MountCommand::buildBackend (Cmdline const & cl)
 	// Call it a day
 	outputMissingRecommends (backend.resolveNeeds (cl.withRecommends));
 	backend.serialize (mountConf);
+
+	if (cl.strategy == "unchanged" && cl.debug)
+	{
+		cout << "The new configuration is:" << endl;
+		std::cout << mountConf;
+		std::cout << "------------------------" << std::endl;
+		cout << "The configuration originally was:" << endl;
+		std::cout << dupMountConf;
+	}
+
+	if (!cl.force && (cl.strategy == "unchanged" && mountConf != dupMountConf))
+	{
+		// throw error because it is not unchanged
+		try
+		{
+			backend.setMountpoint (mpk, dupMountConf);
+		}
+		catch (MountpointAlreadyInUseException const & e)
+		{
+			throw MountpointAlreadyInUseException (
+				std::string ("Requested unchanged mountpoint but mount would lead to changes\n") + e.what ());
+		}
+	}
 }
 
 void MountCommand::readPluginConfig (KeySet & pluginConfig)
diff --git a/src/tools/kdb/mount.hpp b/src/tools/kdb/mount.hpp
index 48bf701acaf..fe1933ef156 100644
--- a/src/tools/kdb/mount.hpp
+++ b/src/tools/kdb/mount.hpp
@@ -35,7 +35,7 @@ class MountCommand : public MountBaseCommand
 
 	virtual std::string getShortOptions () override
 	{
-		return "dfqiR0123cW";
+		return "dfqisR0123cW";
 	}
 
 	virtual std::string getSynopsis () override