LCOV - code coverage report
Current view: top level - src/tools/kdb - cmdline.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 235 315 74.6 %
Date: 2019-09-12 12:28:41 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include <cmdline.hpp>
      10             : 
      11             : #include <backendparser.hpp>
      12             : #include <kdb.hpp>
      13             : #include <kdbconfig.h>
      14             : #include <keysetget.hpp>
      15             : #include <keysetio.hpp>
      16             : 
      17             : #include <cstdio>
      18             : #include <iostream>
      19             : #include <set>
      20             : #include <vector>
      21             : 
      22             : #include <getopt.h>
      23             : 
      24             : #include <command.hpp>
      25             : #include <external.hpp>
      26             : 
      27             : #ifndef _WIN32
      28             : #include <sys/types.h>
      29             : #include <unistd.h>
      30             : #endif
      31             : 
      32             : 
      33             : using namespace std;
      34             : 
      35        3580 : Cmdline::Cmdline (int argc, char ** argv, Command * command)
      36        3580 : : synopsis (command->getSynopsis ()), helpText (), invalidOpt (false),
      37             : 
      38             :   /*XXX: Step 2: initialise your option here.*/
      39             :   debug (), force (), load (), humanReadable (), help (), interactive (), minDepth (0), maxDepth (numeric_limits<int>::max ()),
      40             :   noNewline (), test (), recursive (), resolver (KDB_RESOLVER), strategy ("preserve"), verbose (), quiet (), version (), withoutElektra (),
      41             :   inputFile (""), null (), first (true), second (true), third (true), withRecommends (false), all (), format (KDB_STORAGE), plugins (""),
      42             :   globalPlugins ("spec"), pluginsConfig (""), color ("auto"), ns (""), editor (), bookmarks (), profile ("current"),
      43             : 
      44       96660 :   executable (), commandName ()
      45             : {
      46             :         extern int optind;
      47             :         extern char * optarg;
      48             : 
      49             :         int opt;
      50             : 
      51             :         size_t optionPos;
      52             : 
      53       10740 :         helpText += command->getShortHelpText ();
      54        7160 :         helpText += "\n";
      55       10740 :         helpText += command->getLongHelpText ();
      56        7160 :         helpText += "\n";
      57             : 
      58        7160 :         string allOptions = command->getShortOptions ();
      59        3580 :         allOptions += "HVCpvd";
      60             : 
      61             :         // Make sure to use the unsorted allOptions for getopt to preserve argument chars : and ::
      62       10740 :         std::set<string::value_type> unique_sorted_chars (allOptions.begin (), allOptions.end ());
      63       25060 :         string acceptedOptions (unique_sorted_chars.begin (), unique_sorted_chars.end ());
      64             : 
      65        7160 :         vector<option> long_options;
      66             :         /*XXX: Step 3: give it a long name.*/
      67        3580 :         if (acceptedOptions.find ('a') != string::npos)
      68             :         {
      69         296 :                 option o = { "all", no_argument, nullptr, 'a' };
      70         296 :                 long_options.push_back (o);
      71         592 :                 helpText += "-a --all                 Consider all of the keys.\n";
      72             :         }
      73        3580 :         if (acceptedOptions.find ('d') != string::npos)
      74             :         {
      75        3580 :                 option o = { "debug", no_argument, nullptr, 'd' };
      76        3580 :                 long_options.push_back (o);
      77        7160 :                 helpText += "-d --debug               Give debug information or ask debug questions (in interactive mode).\n";
      78             :         }
      79        3580 :         if (acceptedOptions.find ('f') != string::npos)
      80             :         {
      81         741 :                 option o = { "force", no_argument, nullptr, 'f' };
      82         741 :                 long_options.push_back (o);
      83        1482 :                 helpText += "-f --force               Force the action to be done.\n";
      84             :         }
      85        3580 :         if (acceptedOptions.find ('l') != string::npos)
      86             :         {
      87         429 :                 option o = { "load", no_argument, nullptr, 'f' };
      88         429 :                 long_options.push_back (o);
      89         858 :                 helpText += "-l --load                Load plugin even if system/elektra is available.\n";
      90             :         }
      91        3580 :         if (acceptedOptions.find ('h') != string::npos)
      92             :         {
      93           0 :                 option o = { "human-readable", no_argument, nullptr, 'h' };
      94           0 :                 long_options.push_back (o);
      95           0 :                 helpText += "-h --human-readable      Print numbers in an human readable way.\n";
      96             :         }
      97        3580 :         if (acceptedOptions.find ('H') != string::npos)
      98             :         {
      99        3580 :                 option o = { "help", no_argument, nullptr, 'H' };
     100        3580 :                 long_options.push_back (o);
     101        7160 :                 helpText += "-H --help                Show the man page.\n";
     102             :         }
     103        3580 :         if (acceptedOptions.find ('i') != string::npos)
     104             :         {
     105         308 :                 option o = { "interactive", no_argument, nullptr, 'i' };
     106         308 :                 long_options.push_back (o);
     107         616 :                 helpText += "-i --interactive         Ask the user interactively.\n";
     108             :         }
     109        3580 :         optionPos = acceptedOptions.find ('m');
     110        3580 :         if (optionPos != string::npos)
     111             :         {
     112          72 :                 acceptedOptions.insert (optionPos + 1, ":");
     113          72 :                 option o = { "min-depth", required_argument, nullptr, 'm' };
     114          72 :                 long_options.push_back (o);
     115         144 :                 helpText += "-m --min-depth <min>     Specify the minimum depth (default 0).\n";
     116             :         }
     117        3580 :         optionPos = acceptedOptions.find ('M');
     118        3580 :         if (optionPos != string::npos)
     119             :         {
     120          72 :                 acceptedOptions.insert (optionPos + 1, ":");
     121          72 :                 option o = { "max-depth", required_argument, nullptr, 'M' };
     122          72 :                 long_options.push_back (o);
     123         144 :                 helpText += "-M --max-depth <max>     Specify the maximum depth (unlimited by default).\n";
     124             :         }
     125        3580 :         if (acceptedOptions.find ('n') != string::npos)
     126             :         {
     127         602 :                 option o = { "no-newline", no_argument, nullptr, 'n' };
     128         602 :                 long_options.push_back (o);
     129        1204 :                 helpText += "-n --no-newline          Suppress the newline at the end of the output.\n";
     130             :         }
     131        3580 :         if (acceptedOptions.find ('t') != string::npos)
     132             :         {
     133           0 :                 option o = { "test", no_argument, nullptr, 't' };
     134           0 :                 long_options.push_back (o);
     135           0 :                 helpText += "-t --test                Test.\n";
     136             :         }
     137        3580 :         if (acceptedOptions.find ('r') != string::npos)
     138             :         {
     139         337 :                 option o = { "recursive", no_argument, nullptr, 'r' };
     140         337 :                 long_options.push_back (o);
     141         674 :                 helpText += "-r --recursive           Work in a recursive mode.\n";
     142             :         }
     143        3580 :         optionPos = acceptedOptions.find ('R');
     144        3580 :         if (optionPos != string::npos)
     145             :         {
     146         318 :                 acceptedOptions.insert (optionPos + 1, ":");
     147         318 :                 option o = { "resolver", required_argument, nullptr, 'R' };
     148         318 :                 long_options.push_back (o);
     149         636 :                 helpText += "-R --resolver <name>     Specify the resolver plugin to use.\n";
     150             :         }
     151        3580 :         optionPos = acceptedOptions.find ('p');
     152        3580 :         if (optionPos != string::npos)
     153             :         {
     154        3580 :                 acceptedOptions.insert (optionPos + 1, ":");
     155        3580 :                 option o = { "profile", required_argument, nullptr, 'p' };
     156        3580 :                 long_options.push_back (o);
     157        7160 :                 helpText += "-p --profile <name>      Use a different profile for kdb configuration.\n";
     158             :         }
     159        3580 :         optionPos = acceptedOptions.find ('s');
     160        3580 :         if (optionPos != string::npos)
     161             :         {
     162         394 :                 acceptedOptions.insert (optionPos + 1, ":");
     163         394 :                 option o = { "strategy", required_argument, nullptr, 's' };
     164         394 :                 long_options.push_back (o);
     165         788 :                 helpText += "-s --strategy <name>     Specify the strategy to resolve conflicts.\n";
     166             :         }
     167        3580 :         if (acceptedOptions.find ('v') != string::npos)
     168             :         {
     169        3580 :                 option o = { "verbose", no_argument, nullptr, 'v' };
     170        3580 :                 long_options.push_back (o);
     171        7160 :                 helpText += "-v --verbose             Explain what is happening.\n";
     172             :         }
     173        3580 :         if (acceptedOptions.find ('q') != string::npos)
     174             :         {
     175         755 :                 option o = { "quiet", no_argument, nullptr, 'q' };
     176         755 :                 long_options.push_back (o);
     177        1510 :                 helpText += "-q --quiet               Only print error messages.\n";
     178             :         }
     179        3580 :         if (acceptedOptions.find ('V') != string::npos)
     180             :         {
     181        3580 :                 option o = { "version", no_argument, nullptr, 'V' };
     182        3580 :                 long_options.push_back (o);
     183        7160 :                 helpText += "-V --version             Print version info.\n";
     184             :         }
     185        3580 :         if (acceptedOptions.find ('E') != string::npos)
     186             :         {
     187        1190 :                 option o = { "without-elektra", no_argument, nullptr, 'E' };
     188        1190 :                 long_options.push_back (o);
     189        2380 :                 helpText += "-E --without-elektra     Omit the `/elektra` directory.\n";
     190             :         }
     191        3580 :         optionPos = acceptedOptions.find ('F');
     192        3580 :         if (optionPos != string::npos)
     193             :         {
     194           9 :                 acceptedOptions.insert (optionPos + 1, ":");
     195           9 :                 option o = { "input-file", required_argument, nullptr, 'F' };
     196           9 :                 long_options.push_back (o);
     197          18 :                 helpText += "-F --input-file <plugin>=<file>       Load the given file with the given plugin instead of using the KDB.\n";
     198             :         }
     199        3580 :         optionPos = acceptedOptions.find ('e');
     200        3580 :         if (optionPos != string::npos)
     201             :         {
     202           0 :                 acceptedOptions.insert (optionPos + 1, ":");
     203           0 :                 option o = { "editor", required_argument, 0, 'e' };
     204           0 :                 long_options.push_back (o);
     205           0 :                 helpText += "-e --editor <editor>     Which external editor to use.\n";
     206             :         }
     207        3580 :         if (acceptedOptions.find ('W') != string::npos)
     208             :         {
     209         323 :                 option o = { "with-recommends", no_argument, nullptr, 'W' };
     210         323 :                 long_options.push_back (o);
     211         646 :                 helpText += "-W --with-recommends     Add recommended plugins.\n";
     212             :         }
     213        3580 :         if (acceptedOptions.find ('0') != string::npos)
     214             :         {
     215         397 :                 option o = { "null", no_argument, nullptr, '0' };
     216         397 :                 long_options.push_back (o);
     217         794 :                 helpText += "-0 --null                Use binary 0 termination.\n";
     218             :         }
     219        3580 :         if (acceptedOptions.find ('1') != string::npos)
     220             :         {
     221         307 :                 option o = { "first", no_argument, nullptr, '1' };
     222         307 :                 long_options.push_back (o);
     223         614 :                 helpText += "-1 --first               Suppress the first column.\n";
     224             :         }
     225        3580 :         if (acceptedOptions.find ('2') != string::npos)
     226             :         {
     227         307 :                 option o = { "second", no_argument, nullptr, '2' };
     228         307 :                 long_options.push_back (o);
     229         614 :                 helpText += "-2 --second              Suppress the second column.\n";
     230             :         }
     231        3580 :         if (acceptedOptions.find ('3') != string::npos)
     232             :         {
     233         307 :                 option o = { "third", no_argument, nullptr, '3' };
     234         307 :                 long_options.push_back (o);
     235         614 :                 helpText += "-3 --third               Suppress the third column.\n";
     236             :         }
     237        3580 :         optionPos = acceptedOptions.find ('N');
     238        3580 :         if (acceptedOptions.find ('N') != string::npos)
     239             :         {
     240         715 :                 acceptedOptions.insert (optionPos + 1, ":");
     241         715 :                 option o = { "namespace", required_argument, nullptr, 'N' };
     242         715 :                 long_options.push_back (o);
     243        1430 :                 helpText += "-N --namespace <ns>      Specify the namespace to use for cascading keys.\n";
     244             :         }
     245        3580 :         optionPos = acceptedOptions.find ('c');
     246        3580 :         if (optionPos != string::npos)
     247             :         {
     248        1716 :                 acceptedOptions.insert (optionPos + 1, ":");
     249        1716 :                 option o = { "plugins-config", required_argument, nullptr, 'c' };
     250        1716 :                 long_options.push_back (o);
     251        3432 :                 helpText += "-c --plugins-config <c>  Add a plugin configuration.\n";
     252             :         }
     253        3580 :         optionPos = acceptedOptions.find ('C');
     254        3580 :         if (optionPos != string::npos)
     255             :         {
     256        3580 :                 acceptedOptions.insert (optionPos + 1, ":");
     257        3580 :                 option o = { "color", required_argument, nullptr, 'C' };
     258        3580 :                 long_options.push_back (o);
     259        7160 :                 helpText += "-C --color <when>       Print never/auto(default)/always colored output.\n";
     260             :         }
     261             : 
     262        3580 :         int index = 0;
     263        3580 :         option o = { nullptr, 0, nullptr, 0 };
     264        3580 :         long_options.push_back (o);
     265             : 
     266        7160 :         executable = argv[0];
     267        7160 :         commandName = argv[1];
     268             : 
     269        3580 :         opterr = 0;
     270             : 
     271        8776 :         while ((opt = getopt_long (argc, argv, acceptedOptions.c_str (), &long_options[0], &index)) != EOF)
     272             :         {
     273         808 :                 switch (opt)
     274             :                 {
     275             :                 case 'p':
     276           0 :                         profile = optarg;
     277             :                         break;
     278             :                 default: // ignore everything else for now
     279             :                         break;
     280             :                 }
     281             :         }
     282             : 
     283             : 
     284        7160 :         if (profile != "%")
     285             :         {
     286             :                 try
     287             :                 {
     288             :                         using namespace kdb;
     289             :                         /*XXX: Step 4: use default from KDB, if available.*/
     290        7160 :                         KDB kdb;
     291        7160 :                         KeySet conf;
     292             : 
     293       14320 :                         for (int i = 0; i <= 2; ++i)
     294             :                         {
     295       21480 :                                 std::string dirname;
     296       10740 :                                 switch (i)
     297             :                                 {
     298             :                                 // prefer later dirnames (will override)
     299             :                                 case 0:
     300       10740 :                                         dirname = "/sw/kdb/" + profile + "/";
     301        3580 :                                         break; // legacy
     302             :                                 case 1:
     303             :                                         dirname = "/sw/elektra/kdb/#0/%/";
     304             :                                         break; // no profile
     305             :                                 case 2:
     306       10740 :                                         dirname = "/sw/elektra/kdb/#0/" + profile + "/";
     307        3580 :                                         break; // current profile
     308             :                                 }
     309             : 
     310       10740 :                                 kdb.get (conf, dirname);
     311             : 
     312       42960 :                                 Key k = conf.lookup (dirname + "resolver");
     313       10740 :                                 if (k) resolver = k.get<string> ();
     314             : 
     315       53700 :                                 k = conf.lookup (dirname + "format");
     316       10740 :                                 if (k) format = k.get<string> ();
     317             : 
     318       53700 :                                 k = conf.lookup (dirname + "plugins");
     319       10740 :                                 if (k) plugins = k.get<string> ();
     320             : 
     321       53700 :                                 k = conf.lookup (dirname + "plugins/global");
     322       10740 :                                 if (k) globalPlugins = k.get<string> ();
     323             : 
     324       53700 :                                 k = conf.lookup (dirname + "namespace");
     325       10740 :                                 if (k) ns = k.get<string> ();
     326             : 
     327       53700 :                                 k = conf.lookup (dirname + "verbose");
     328       10740 :                                 if (k) verbose = k.get<bool> ();
     329             : 
     330       53700 :                                 k = conf.lookup (dirname + "quiet");
     331       10740 :                                 if (k) quiet = k.get<bool> ();
     332             : 
     333       53700 :                                 k = conf.lookup (dirname + "editor");
     334       10740 :                                 if (k) editor = k.get<string> ();
     335             : 
     336       53700 :                                 k = conf.lookup (dirname + "recommends");
     337       10740 :                                 if (k) withRecommends = k.get<bool> ();
     338             : 
     339       42960 :                                 map nks = conf.get<map> (dirname + "bookmarks");
     340       32220 :                                 bookmarks.insert (nks.begin (), nks.end ());
     341             : 
     342       53700 :                                 k = conf.lookup (dirname + "color");
     343       10740 :                                 if (k) color = k.get<std::string> ();
     344             :                         }
     345             :                 }
     346           0 :                 catch (kdb::KDBException const & ce)
     347             :                 {
     348           0 :                         std::cerr << "Sorry, I could not fetch my own configuration:\n" << ce.what () << std::endl;
     349             :                 }
     350             :         }
     351             : 
     352             :         // reinit
     353        3580 :         index = 0;
     354        3580 :         optind = 1;
     355             : 
     356        3580 :         if (!dynamic_cast<ExternalCommand *> (command))
     357             :         {
     358             :                 // do not print to stderr for external commands,
     359             :                 // we do not know which options they have and
     360             :                 // otherwise maybe wrong "invalid/unrecognized option"
     361             :                 // are reported to stderr.
     362        3502 :                 opterr = 1;
     363             :         }
     364             : 
     365        8776 :         while ((opt = getopt_long (argc, argv, acceptedOptions.c_str (), &long_options[0], &index)) != EOF)
     366             :         {
     367         808 :                 switch (opt)
     368             :                 {
     369             :                 /*XXX: Step 5: and now process the option.*/
     370             :                 case 'a':
     371           0 :                         all = true;
     372           0 :                         break;
     373             :                 case 'C':
     374           0 :                         color = optarg;
     375           0 :                         if (color != "never" && color != "auto" && color != "always")
     376             :                         {
     377           0 :                                 std::cerr << argv[0] << ": -C --color needs never, auto, or always as argument\n";
     378           0 :                                 invalidOpt = true;
     379             :                         }
     380             :                         break;
     381             :                 case 'd':
     382           2 :                         debug = true;
     383           2 :                         break;
     384             :                 case 'e':
     385           0 :                         editor = optarg;
     386             :                         break;
     387             :                 case 'f':
     388           6 :                         force = true;
     389           6 :                         break;
     390             :                 case 'F':
     391           0 :                         inputFile = optarg;
     392             :                         break;
     393             :                 case 'h':
     394           0 :                         humanReadable = true;
     395           0 :                         break;
     396             :                 case 'l':
     397           0 :                         load = true;
     398           0 :                         break;
     399             :                 case 'H':
     400           0 :                         help = true;
     401           0 :                         break;
     402             :                 case 'i':
     403           0 :                         interactive = true;
     404           0 :                         break;
     405             :                 case 'm':
     406             :                         try
     407             :                         {
     408          10 :                                 minDepth = stoi (optarg);
     409             :                         }
     410           0 :                         catch (std::invalid_argument const & ia)
     411             :                         {
     412           0 :                                 std::cerr << argv[0] << ": -m --min-depth needs a valid number as argument\n";
     413           0 :                                 invalidOpt = true;
     414             :                         }
     415             :                         break;
     416             :                 case 'M':
     417             :                         try
     418             :                         {
     419          50 :                                 maxDepth = stoi (optarg);
     420             :                         }
     421           0 :                         catch (std::invalid_argument const & ia)
     422             :                         {
     423           0 :                                 std::cerr << argv[0] << ": -M --max-depth needs a valid number as argument\n";
     424           0 :                                 invalidOpt = true;
     425             :                         }
     426             : 
     427          10 :                         if (maxDepth == -1)
     428             :                         {
     429           0 :                                 maxDepth = numeric_limits<int>::max ();
     430             :                         }
     431             :                         break;
     432             :                 case 'n':
     433         139 :                         noNewline = true;
     434         139 :                         break;
     435             :                 case 't':
     436           0 :                         test = true;
     437           0 :                         break;
     438             :                 case 'r':
     439         254 :                         recursive = true;
     440         254 :                         break;
     441             :                 case 'p':
     442             :                         break; // already handled above
     443             :                 case 'R':
     444          67 :                         resolver = optarg;
     445             :                         break;
     446             :                 case 's':
     447           0 :                         strategy = optarg;
     448             :                         break;
     449             :                 case 'v':
     450           8 :                         verbose = true;
     451           8 :                         break;
     452             :                 case 'q':
     453           0 :                         quiet = true;
     454           0 :                         break;
     455             :                 case 'V':
     456           0 :                         version = true;
     457           0 :                         break;
     458             :                 case 'E':
     459         136 :                         withoutElektra = true;
     460         136 :                         break;
     461             :                 case 'W':
     462           2 :                         withRecommends = true;
     463           2 :                         break;
     464             :                 case '0':
     465           0 :                         null = true;
     466           0 :                         break;
     467             :                 case '1':
     468           0 :                         first = false;
     469           0 :                         break;
     470             :                 case '2':
     471           0 :                         second = false;
     472           0 :                         break;
     473             :                 case '3':
     474           0 :                         third = false;
     475           0 :                         break;
     476             :                 case 'N':
     477         175 :                         ns = optarg;
     478             :                         break;
     479             :                 case 'c':
     480           5 :                         pluginsConfig = optarg;
     481             :                         break;
     482             : 
     483             :                 default:
     484           2 :                         invalidOpt = true;
     485           2 :                         break;
     486             :                 }
     487             :         }
     488             : 
     489        3580 :         if (quiet && verbose)
     490             :         {
     491           0 :                 std::cout << "Both quiet and verbose is active: will suppress default messages, but print verbose messages" << std::endl;
     492             :         }
     493             : 
     494        7160 :         if (ns.empty ())
     495             :         {
     496             : #ifndef _WIN32
     497        3405 :                 if (getuid () == 0 || geteuid () == 0)
     498             :                 {
     499           0 :                         ns = "system";
     500             :                 }
     501             :                 else
     502             :                 {
     503        3405 :                         ns = "user";
     504             :                 }
     505             : #else
     506             :                 ns = "user";
     507             : #endif
     508             :         }
     509             : 
     510        3580 :         optind++; // skip the command name
     511       15646 :         while (optind < argc)
     512             :         {
     513       30165 :                 arguments.push_back (argv[optind++]);
     514             :         }
     515             : 
     516             :         // init colors
     517        3580 :         hasStdColor (color);
     518        3580 :         hasErrorColor (color);
     519        3580 : }
     520             : 
     521        1613 : kdb::KeySet Cmdline::getPluginsConfig (string basepath) const
     522             : {
     523        1613 :         return kdb::tools::parsePluginArguments (pluginsConfig, basepath);
     524             : }
     525             : 
     526             : /**
     527             :  * @brief create a key from argument number pos
     528             :  *
     529             :  * @param pos the position in cl.arguments that tells us the name of the key to create
     530             :  *
     531             :  * @throw invalid_argument if the argument is not a valid keyname
     532             :  *
     533             :  * @return a newly created key from the name found in cl.arguments[pos]
     534             :  */
     535        2881 : kdb::Key Cmdline::createKey (int pos, bool allowCascading) const
     536             : {
     537       11524 :         std::string name = arguments[pos];
     538             :         // std::cerr << "Using " << name << std::endl;
     539             :         // for (auto const & n : bookmarks) std::cout << "nks: " << n.second << std::endl;
     540        2881 :         if (name.empty ())
     541             :         {
     542          14 :                 throw invalid_argument ("<empty string> is not a valid keyname. Please enter a valid one.");
     543             :         }
     544             : 
     545        5734 :         kdb::Key root (name, KEY_END);
     546             : 
     547        2867 :         if (name[0] == '+')
     548             :         {
     549           0 :                 kdb::Key bookmark = resolveBookmark (name);
     550           0 :                 if (!bookmark.isValid ())
     551             :                 {
     552           0 :                         throw invalid_argument ("cannot find bookmark " + bookmark.getFullName ());
     553             :                 }
     554           0 :                 root = bookmark;
     555             :         }
     556             : 
     557        2867 :         if (!root.isValid ())
     558             :         {
     559           0 :                 throw invalid_argument (name + " is not a valid keyname" + "\n\n" +
     560             :                                         "For absolute keys (starting without '/'), please note that only one of the predefined namespaces "
     561           0 :                                         "can be used (see 'man elektra-namespaces').\n" +
     562           0 :                                         "Please also ensure that the path is separated by a '/'.\n" +
     563           0 :                                         "An example for a valid absolute key is user/a/key, and for a valid cascading key /a/key.");
     564             :         }
     565             : 
     566        2895 :         if (!allowCascading && root.isCascading ())
     567             :         {
     568           0 :                 throw invalid_argument ("The key '" + root.getName () +
     569           0 :                                         "'is a cascading keyname, which is not supported. Please choose a namespace.");
     570             :         }
     571             : 
     572        2867 :         return root;
     573             : }
     574             : 
     575             : /**
     576             :  * @brief resolve the bookmark with the given name
     577             :  *
     578             :  * @param bookmark the name of the bookmark to resolve
     579             :  *
     580             :  * @return a key to the resolved bookmark, or an invalid key if no bookmark with the given name exists
     581             :  */
     582           0 : kdb::Key Cmdline::resolveBookmark (std::string name) const
     583             : {
     584           0 :         if (!name.empty () && name[0] == '+')
     585             :         {
     586           0 :                 size_t found = name.find ('/');
     587           0 :                 std::string bookmark;
     588           0 :                 std::string restKey;
     589           0 :                 if (found != std::string::npos)
     590             :                 {
     591           0 :                         bookmark = name.substr (1, found - 1);
     592           0 :                         restKey = name.substr (found, name.length () - found);
     593             :                 }
     594             :                 else
     595             :                 {
     596           0 :                         bookmark = name.substr (1, name.length () - 1);
     597             :                 }
     598           0 :                 auto realKeyIt = bookmarks.find (bookmark);
     599           0 :                 std::string realKey;
     600           0 :                 if (realKeyIt != bookmarks.end ())
     601             :                 {
     602           0 :                         realKey = realKeyIt->second;
     603           0 :                         name = realKey + "/" + restKey;
     604           0 :                         if (verbose)
     605             :                         {
     606           0 :                                 std::cout << "using bookmark " << bookmark << " which is: " << realKey << "-" << restKey << std::endl;
     607             :                         }
     608           0 :                         return kdb::Key (name, KEY_END);
     609             :                 }
     610             :         }
     611             :         return kdb::Key ();
     612             : }
     613             : 
     614          17 : std::ostream & operator<< (std::ostream & os, Cmdline & cl)
     615             : {
     616          17 :         if (cl.invalidOpt)
     617             :         {
     618           2 :                 os << "Sorry, I could not process the given options (see errors above)\n" << endl;
     619             :         }
     620             : 
     621         119 :         os << "Usage: " << cl.executable << " " << cl.commandName << " " << cl.synopsis;
     622          51 :         os << "\n\n" << cl.helpText;
     623          17 :         return os;
     624        7164 : }

Generated by: LCOV version 1.13