LCOV - code coverage report
Current view: top level - src/tools/kdb - editor.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 5 98 5.1 %
Date: 2019-09-12 12:28:41 Functions: 4 7 57.1 %

          Line data    Source code
       1             : #include <editor.hpp>
       2             : 
       3             : #include <sys/stat.h>
       4             : #include <sys/types.h>
       5             : #include <unistd.h>
       6             : 
       7             : #include <cmdline.hpp>
       8             : #include <external.hpp>
       9             : #include <kdb.hpp>
      10             : #include <keysetio.hpp>
      11             : #include <modules.hpp>
      12             : 
      13             : #include <kdbmacros.h>
      14             : 
      15             : #include <export.hpp>
      16             : #include <import.hpp>
      17             : 
      18             : #include <iostream>
      19             : #include <string>
      20             : 
      21             : #include <mergehelper.hpp>
      22             : #include <merging/metamergestrategy.hpp>
      23             : #include <merging/threewaymerge.hpp>
      24             : 
      25             : using namespace kdb;
      26             : using namespace kdb::tools;
      27             : using namespace kdb::tools::merging;
      28             : using namespace std;
      29             : 
      30         156 : EditorCommand::EditorCommand ()
      31             : {
      32          78 : }
      33             : 
      34         234 : EditorCommand::~EditorCommand ()
      35             : {
      36         156 : }
      37             : 
      38           0 : void EditorCommand::tmpFile ()
      39             : {
      40             : #ifndef _WIN32
      41           0 :         const char * tmpvar = getenv ("TMPDIR");
      42           0 :         if (!tmpvar)
      43             :         {
      44           0 :                 tmpvar = "/tmp";
      45             :         }
      46           0 :         filename = tmpvar;
      47           0 :         filename += "/elektra-test.XXXXXX";
      48           0 :         char * fn = static_cast<char *> (malloc (filename.length () + 1));
      49           0 :         strcpy (fn, filename.c_str ());
      50           0 :         int fd = mkstemp (fn);
      51           0 :         filename = std::string (fn);
      52           0 :         close (fd);
      53           0 :         free (fn);
      54             : #endif
      55           0 : }
      56             : 
      57           0 : bool runAllEditors (std::string const & filename)
      58             : {
      59             :         using namespace kdb;
      60           0 :         if (runEditor ("/usr/bin/sensible-editor", filename)) return true;
      61           0 :         if (runEditor ("/usr/bin/editor", filename)) return true;
      62           0 :         char * editor = getenv ("EDITOR");
      63           0 :         if (editor && runEditor (editor, filename)) return true;
      64           0 :         if (runEditor ("/usr/bin/vi", filename)) return true;
      65           0 :         if (runEditor ("/bin/vi", filename)) return true;
      66           0 :         return false;
      67             : }
      68             : 
      69             : class EditorNotAvailable : public std::exception
      70             : {
      71             :         virtual const char * what () const throw () override
      72             :         {
      73             :                 return "kdb-editor not available for windows (non-POSIX systems)";
      74             :         }
      75             : };
      76             : 
      77           0 : int EditorCommand::execute (Cmdline const & cl)
      78             : {
      79             : #ifdef _WIN32
      80             :         throw EditorNotAvailable ();
      81             : #endif
      82             : 
      83           0 :         int argc = cl.arguments.size ();
      84           0 :         if (argc < 1)
      85             :         {
      86           0 :                 throw invalid_argument ("wrong number of arguments, 1 needed");
      87             :         }
      88           0 :         Key root = cl.createKey (0);
      89             : 
      90           0 :         KeySet ours;
      91           0 :         KDB kdb;
      92           0 :         kdb.get (ours, root);
      93           0 :         KeySet oursToEdit = ours.cut (root);
      94           0 :         KeySet original = oursToEdit.dup ();
      95             : 
      96           0 :         if (cl.strategy == "validate")
      97             :         {
      98           0 :                 prependNamespace (oursToEdit, cl.ns);
      99           0 :                 oursToEdit.cut (prependNamespace (root, cl.ns));
     100             :         }
     101             : 
     102             :         // export it to file
     103           0 :         string format = cl.format;
     104           0 :         if (argc > 1) format = cl.arguments[1];
     105             : 
     106           0 :         Modules modules;
     107           0 :         PluginPtr plugin = modules.load (format);
     108             : 
     109           0 :         tmpFile ();
     110           0 :         if (cl.verbose) std::cout << "filename set to " << filename << std::endl;
     111           0 :         Key errorKey (root);
     112           0 :         errorKey.setString (filename);
     113             :         struct stat orig;
     114           0 :         stat (filename.c_str (), &orig);
     115             : 
     116           0 :         if (plugin->set (oursToEdit, errorKey) == -1)
     117             :         {
     118           0 :                 printWarnings (cerr, errorKey, cl.verbose, cl.debug);
     119           0 :                 printError (cerr, errorKey, cl.verbose, cl.debug);
     120             :                 return 11;
     121             :         }
     122             : 
     123           0 :         printWarnings (cerr, errorKey, cl.verbose, cl.debug);
     124             : 
     125             : 
     126             :         // start editor
     127           0 :         if (cl.verbose) std::cout << "running editor with " << filename << std::endl;
     128           0 :         if (!cl.editor.empty ())
     129             :         {
     130           0 :                 if (!runEditor (cl.editor, filename))
     131             :                 {
     132           0 :                         std::cerr << "Could not run editor " << cl.editor << std::endl;
     133             :                         return 12;
     134             :                 }
     135             :         }
     136             :         else
     137             :         {
     138           0 :                 if (!runAllEditors (filename))
     139             :                 {
     140           0 :                         std::cerr << "Could not run any editor, please change /sw/elektra/kdb/#0/current/editor" << std::endl;
     141             :                         return 12;
     142             :                 }
     143             :         }
     144             : 
     145             :         struct stat modif;
     146           0 :         stat (filename.c_str (), &modif);
     147             : 
     148           0 :         if (ELEKTRA_STAT_SECONDS (orig) == ELEKTRA_STAT_SECONDS (modif) &&
     149           0 :             ELEKTRA_STAT_NANO_SECONDS (orig) == ELEKTRA_STAT_NANO_SECONDS (modif))
     150             :         {
     151           0 :                 if (!cl.quiet) std::cout << "File was unchanged, will exit successfully";
     152             :                 return 0;
     153             :         }
     154             : 
     155             :         // import from the file
     156           0 :         KeySet importedKeys;
     157           0 :         plugin->get (importedKeys, errorKey);
     158           0 :         importedKeys = importedKeys.cut (root);
     159             : 
     160           0 :         printWarnings (cerr, errorKey, cl.verbose, cl.debug);
     161           0 :         printError (cerr, errorKey, cl.verbose, cl.debug);
     162             : 
     163           0 :         if (cl.strategy == "validate")
     164             :         {
     165           0 :                 applyMeta (importedKeys, original);
     166           0 :                 kdb.set (importedKeys, root);
     167           0 :                 printWarnings (cerr, root, cl.verbose, cl.debug);
     168           0 :                 printError (cerr, root, cl.verbose, cl.debug);
     169             :                 return 0;
     170             :         }
     171             : 
     172           0 :         ThreeWayMerge merger;
     173           0 :         MergeHelper helper;
     174             : 
     175           0 :         helper.configureMerger (cl, merger);
     176             :         MergeResult result = merger.mergeKeySet (
     177           0 :                 MergeTask (BaseMergeKeys (oursToEdit, root), OurMergeKeys (oursToEdit, root), TheirMergeKeys (importedKeys, root), root));
     178             : 
     179           0 :         helper.reportResult (cl, result, cout, cerr);
     180             : 
     181           0 :         int ret = 13;
     182           0 :         if (!result.hasConflicts ())
     183             :         {
     184           0 :                 if (cl.verbose)
     185             :                 {
     186           0 :                         cout << "The merged keyset with strategy " << cl.strategy << " is:" << endl;
     187           0 :                         cout << result.getMergedKeys ();
     188             :                 }
     189             : 
     190           0 :                 KeySet resultKeys = result.getMergedKeys ();
     191           0 :                 if (cl.verbose) std::cout << "about to write result keys " << resultKeys << std::endl;
     192           0 :                 ours.append (resultKeys);
     193             :                 try
     194             :                 {
     195           0 :                         kdb.set (ours, root);
     196           0 :                         if (cl.verbose) std::cout << "successful, cleaning up " << filename << std::endl;
     197           0 :                         unlink (filename.c_str ());
     198           0 :                         ret = 0;
     199             :                 }
     200           0 :                 catch (KDBException const & e)
     201             :                 {
     202           0 :                         std::cout << "Import of configuration failed with the error:\n";
     203           0 :                         std::cout << e.what ();
     204           0 :                         std::cout << "\n\n";
     205           0 :                         std::cout << "Your changes are not lost." << std::endl;
     206           0 :                         std::cout << "Please fix, import and remove \"" << filename << '"' << std::endl;
     207           0 :                         ret = 14;
     208             :                 }
     209             :         }
     210             :         else
     211             :         {
     212           0 :                 std::cout << "Import not successful, please import and remove \"" << filename << '"' << std::endl;
     213             :         }
     214             : 
     215           0 :         return ret;
     216        7164 : }

Generated by: LCOV version 1.13