<commit_before>#include <mount.hpp>

#include <algorithm>
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <string>

#include <kdbinternal.h>

using namespace std;
using namespace kdb;

std::string MountCommand::root = "system/elektra/mountpoints";

MountCommand::MountCommand()
{}

bool MountCommand::checkFile(std::string path)
{
	if (path[0] != '/')
	{
		cerr << "You must use an absolute path" << endl;
		return false;
	}
	std::ofstream f(path.c_str());
	return f.is_open();
}

KeySet MountCommand::addPlugins(std::string name, std::string which)
{
	KeySet ret;
	ret.append (*Key (root + "/" + name + "/" + which + "plugins",
		KEY_COMMENT, "List of plugins to use",
		KEY_END));

	cout << "Now you have to provide some " << which << " plugins which should be used for that backend" << endl;
	cout << "Exactly one plugin must be a storage plugin" << endl;
	for (int i=0; i<10; ++i)
	{
		cout << "Enter the " << i << " plugin to use." << endl;
		cout << "Write \".\" as name in a single line if you are finished" << endl;
		cout << "Name of the " << which << " plugin: ";
		std::string pluginName;
		cin >> pluginName;
		if (pluginName == ".") break;

		cout << "Enter a path to a file in the filesystem." << endl;
		cout << ". for no path (use global one)" << endl;
		cout << "Path: ";
		std::string path;
		cin >> path;
		if (path != "." && !checkFile(path))
		{
			cerr << "Warning: Could not open path, will continue with no path" << endl;
			path = ".";
		}

		KeySet testConfig(1,
			*Key(	"system/path",
				KEY_VALUE, path.c_str(),
				KEY_COMMENT, "Test config for loading a plugin.",
				KEY_END),
			KS_END);

		ckdb::Plugin *plugin = ckdb::pluginOpen(pluginName.c_str(), testConfig.dup());
		if (plugin && which == "get")
		{
			if (!plugin->kdbGet)
			{
				cout << "get symbol missing" << endl;
				plugin = 0;
			}
		}
		if (plugin && which == "set")
		{
			if (!plugin->kdbSet)
			{
				cout << "set symbol missing" << endl;
				plugin = 0;
			}
		}
		ckdb::pluginClose(plugin);
		if (!plugin)
		{
			cout << "Was not able to load such a plugin!" << endl;
			cout << "or it had no " << which << " symbol exported (see above)" << endl;
			cout << "Do you want to (P)roceed with next plugin (current will be left empty)?" << endl;
			cout << "Do you want to go (B)ack to the first plugin?" << endl;
			cout << "Do you want to (R)etry this plugin?" << endl;
			cout << "Do you want to (F)inish entering plugins?" << endl;
			cout << "Or do you want to (A)bort?" << endl;
			cout << "Please provide action: ";
			string answer;
			cin >> answer;
			if (answer == "P" || answer == "Proceed" || answer == "(P)roceed" || answer == "p")
			{
				continue;
			} else if (answer == "R" || answer == "Retry" || answer == "(R)etry" || answer == "r")
			{
				--i;
				continue;
			} else if (answer == "B" || answer == "Back" || answer == "(B)ack" || answer == "b")
			{
				cout << endl;
				return KeySet(static_cast<ckdb::KeySet*>(0));
			} else if (answer == "F" || answer == "Finish" || answer == "(F)inish" || answer == "f")
			{
				break;
			} else throw CommandAbortException();
		}

		std::ostringstream pluginNumber;
		pluginNumber << i;
		ret.append (*Key (root + "/" + name + "/" + which + std::string("plugins/#") + pluginNumber.str() + pluginName,
			KEY_COMMENT, "A plugin",
			KEY_END));
		if (path != ".")
		{
			ret.append (*Key (root + "/" + name + "/" + which + std::string("plugins/#") + pluginNumber.str() + pluginName + "/config",
				KEY_COMMENT, "The configuration for the specific plugin.\n"
				"All keys below that directory will be passed to plugin.\n"
				"These keys have backend specific meaning.\n"
				"See documentation http://www.libelektra.org for which keys must or can be set.\n"
				"Here the most important keys should be preloaded.",
				KEY_END));
			ret.append (*Key (root + "/" + name + "/" + which + "plugins/#" + pluginNumber.str() + pluginName + "/config/path",
				KEY_VALUE, path.c_str(),
				KEY_COMMENT, "The path where the config file is located."
				"This item is often used by backends using configuration in a filesystem"
				"to know there relative location of the keys to fetch or write.",
				KEY_END));
		}
	}

	cout << endl;
	return ret;
}

int MountCommand::execute(int , char** )
{
	cout << "Welcome to interactive mounting" << endl;<commit_msg>storage plugins check<commit_after>#include <mount.hpp>

#include <algorithm>
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
#include <string>

#include <kdbinternal.h>

using namespace std;
using namespace kdb;

std::string MountCommand::root = "system/elektra/mountpoints";

MountCommand::MountCommand()
{}

bool MountCommand::checkFile(std::string path)
{
	if (path[0] != '/')
	{
		cerr << "You must use an absolute path" << endl;
		return false;
	}
	std::ofstream f(path.c_str());
	return f.is_open();
}

KeySet MountCommand::addPlugins(std::string name, std::string which)
{
	KeySet ret;
	int nrStoragePlugins = 0;
	ret.append (*Key (root + "/" + name + "/" + which + "plugins",
		KEY_COMMENT, "List of plugins to use",
		KEY_END));

	cout << "Now you have to provide some " << which << " plugins which should be used for that backend" << endl;
	cout << "Exactly one plugin must be a storage plugin" << endl;
	for (int i=0; i<10; ++i)
	{
		cout << "Enter the " << i << " plugin to use." << endl;
		cout << "Write \".\" as name in a single line if you are finished" << endl;
		cout << "Name of the " << which << " plugin: ";
		std::string pluginName;
		cin >> pluginName;
		if (pluginName == ".") break;

		cout << "Enter a path to a file in the filesystem." << endl;
		cout << ". for no path (use global one)" << endl;
		cout << "Path: ";
		std::string path;
		cin >> path;
		if (path != "." && !checkFile(path))
		{
			cerr << "Warning: Could not open path, will continue with no path" << endl;
			path = ".";
		}

		KeySet testConfig(1,
			*Key(	"system/path",
				KEY_VALUE, path.c_str(),
				KEY_COMMENT, "Test config for loading a plugin.",
				KEY_END),
			KS_END);

		bool isStoragePlugin = false;
		ckdb::Plugin *plugin = ckdb::pluginOpen(pluginName.c_str(), testConfig.dup());
		if (plugin)
		{
			if (std::string(plugin->provides).find("storage") != string::npos)
			{
				cout << "This is a storage plugin" << endl;
				++ nrStoragePlugins;
				isStoragePlugin = true;
			}
			if (std::string(plugin->licence).find("BSD") == string::npos)
			{
				cout << "Warning this plugin is not BSD licenced" << endl;
				cout << "It might taint the licence of the overall product" << endl;
				cout << "Its licence is: " << plugin->licence << endl;
			}
			if (which == "get")
			{
				if (!plugin->kdbGet)
				{
					cout << "get symbol missing" << endl;
					plugin = 0;
				}
			}
			else if (which == "set")
			{
				if (!plugin->kdbSet)
				{
					cout << "set symbol missing" << endl;
					plugin = 0;
				}
			}
		}
		ckdb::pluginClose(plugin);
		if (!plugin || nrStoragePlugins>1)
		{
			if (!plugin)
			{
				cout << "Was not able to load such a plugin!" << endl;
				cout << "or it had no " << which << " symbol exported (see above)" << endl;
			}
			if (nrStoragePlugins>1) cout << "Already to many storage plugins" << endl;
			cout << "Do you want to (P)roceed with next plugin (current will be left empty)?" << endl;
			cout << "Do you want to go (B)ack to the first plugin?" << endl;
			cout << "Do you want to (R)etry this plugin?" << endl;
			cout << "Do you want to (F)inish entering plugins?" << endl;
			cout << "Or do you want to (A)bort?" << endl;
			cout << "Please provide action: ";
			string answer;
			cin >> answer;
			if (answer == "P" || answer == "Proceed" || answer == "(P)roceed" || answer == "p")
			{
				if (isStoragePlugin) --nrStoragePlugins;
				continue;
			} else if (answer == "R" || answer == "Retry" || answer == "(R)etry" || answer == "r")
			{
				if (isStoragePlugin) --nrStoragePlugins;
				--i;
				continue;
			} else if (answer == "B" || answer == "Back" || answer == "(B)ack" || answer == "b")
			{
				cout << endl;
				return KeySet(static_cast<ckdb::KeySet*>(0));
			} else if (answer == "F" || answer == "Finish" || answer == "(F)inish" || answer == "f")
			{
				if (isStoragePlugin) --nrStoragePlugins;
				break;
			}
			throw CommandAbortException();
		}

		std::ostringstream pluginNumber;
		pluginNumber << i;
		ret.append (*Key (root + "/" + name + "/" + which + std::string("plugins/#") + pluginNumber.str() + pluginName,
			KEY_COMMENT, "A plugin",
			KEY_END));
		if (path != ".")
		{
			ret.append (*Key (root + "/" + name + "/" + which + std::string("plugins/#") + pluginNumber.str() + pluginName + "/config",
				KEY_COMMENT, "The configuration for the specific plugin.\n"
				"All keys below that directory will be passed to plugin.\n"
				"These keys have backend specific meaning.\n"
				"See documentation http://www.libelektra.org for which keys must or can be set.\n"
				"Here the most important keys should be preloaded.",
				KEY_END));
			ret.append (*Key (root + "/" + name + "/" + which + "plugins/#" + pluginNumber.str() + pluginName + "/config/path",
				KEY_VALUE, path.c_str(),
				KEY_COMMENT, "The path where the config file is located."
				"This item is often used by backends using configuration in a filesystem"
				"to know there relative location of the keys to fetch or write.",
				KEY_END));
		}
	}

	if (nrStoragePlugins != 1)
	{
		cerr << "You need to provide a storage plugin, but did not" << endl;
		cerr << "Will go back to the first plugin" << endl;
		cout << endl;
		return KeySet(static_cast<ckdb::KeySet*>(0));
	}

	cout << endl;
	return ret;
}

int MountCommand::execute(int , char** )
{
	cout << "Welcome to interactive mounting" << endl;
{'fraction_non_alphanumeric': 0.1716663242243682, 'fraction_numerical': 0.002157386480378056, 'mean_word_length': 3.2436791630340016, 'pattern_counts': {'":': 0, '<': 256, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2710801', 'n_tokens_mistral': 3688, 'n_tokens_neox': 3225, 'n_words': 1058}