Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
kdb-cli: rewrite cp
Browse files Browse the repository at this point in the history
  • Loading branch information
hannes99 committed Mar 2, 2023
1 parent ca36161 commit 4f13f81
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 165 deletions.
148 changes: 148 additions & 0 deletions src/tools/kdb/cp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/**
* @file
*
* @brief Implementation of kdb cp command
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*/

#include <command.h>
#include <cp.h>

#include <kdb.h>
#include <kdbassert.h>
#include <kdbease.h>
#include <kdberrors.h>
#include <stdio.h>
#include <string.h>

#define COMMAND_NAME "cp"

#define GET_OPTION_KEY(options, name) GET_OPT_KEY (options, COMMAND_BASE_KEY (COMMAND_NAME) "/" name)
#define GET_OPTION(options, name) GET_OPT (options, COMMAND_BASE_KEY (COMMAND_NAME) "/" name)

void addCpSpec (KeySet * spec)
{
ksAppendKey (spec, keyNew (COMMAND_SPEC_KEY (COMMAND_NAME), KEY_META, "description",
"Copy a configuration within the key database.", KEY_META, "command", COMMAND_NAME, KEY_END));
ksAppendKey (spec, keyNew (COMMAND_SPEC_KEY (COMMAND_NAME) "/recursive", KEY_META, "description", "Work in recursive mode.",
KEY_META, "opt", "r", KEY_META, "opt/long", "recursive", KEY_META, "opt/arg", "none", KEY_END));
ksAppendKey (spec, keyNew (COMMAND_SPEC_KEY (COMMAND_NAME) "/source", KEY_META, "description", "The source key", KEY_META, "args",
"indexed", KEY_META, "args/index", "0", KEY_END));
ksAppendKey (spec, keyNew (COMMAND_SPEC_KEY (COMMAND_NAME) "/destination", KEY_META, "description", "The destination key", KEY_META,
"args", "indexed", KEY_META, "args/index", "1", KEY_END));

ADD_BASIC_OPTIONS (spec, COMMAND_SPEC_KEY (COMMAND_NAME))
}

int execCp (KeySet * options, Key * errorKey)
{
int ret = 0;
GET_BASIC_OPTIONS

bool recursive = false;
tmp = GET_OPTION_KEY (options, "recursive");
if (tmp != NULL)
{
elektraKeyToBoolean (GET_OPTION_KEY (options, "recursive"), &recursive);
}

const char * sourceName = getKeyNameFromOptions (options, GET_OPTION (options, "source"), errorKey, verbose);
if (sourceName == NULL) return 1;

const char * destName = getKeyNameFromOptions (options, GET_OPTION (options, "destination"), errorKey, verbose);
if (destName == NULL)
{
elektraFree ((void *) sourceName);
return 1;
}

Key * sourceKey = keyNew (sourceName, KEY_END);
Key * destKey = keyNew (destName, KEY_END);

if (keyGetNamespace (sourceKey) == KEY_NS_NONE || keyGetNamespace (sourceKey) == KEY_NS_CASCADING) {
ret = 1;
ELEKTRA_SET_VALIDATION_SYNTACTIC_ERROR (errorKey, "source key does not specify a namespace");
elektraFree ((void*) sourceName);
elektraFree ((void*) destName);
keyDel (sourceKey);
keyDel (destKey);
return ret;
}
if (keyGetNamespace (destKey) == KEY_NS_NONE || keyGetNamespace (destKey) == KEY_NS_CASCADING) {
ret = 1;
ELEKTRA_SET_VALIDATION_SYNTACTIC_ERROR (errorKey, "destination key does not specify a namespace");
elektraFree ((void*) sourceName);
elektraFree ((void*) destName);
keyDel (sourceKey);
keyDel (destKey);
return ret;
}

Key * root = keyNew ("/", KEY_END);

KeySet * conf = ksNew (0, KS_END);
KDB * handle = kdbOpen (NULL, errorKey);
if (kdbGet (handle, conf, root) == -1)
{
ELEKTRA_SET_VALIDATION_SEMANTIC_ERRORF (errorKey, "could not load '%s': %s", sourceName, GET_ERR (root));
ret = 1;
goto cleanup;
}

Key * cur = NULL;


size_t sourceNameLen = elektraStrLen (keyName (sourceKey));
size_t destNameLen = elektraStrLen (keyName (destKey));

long count = 0;
KeySet * newConf = ksNew (ksGetSize (conf), KS_END);
for (elektraCursor it = 0; it < ksGetSize (conf); ++it)
{
cur = ksAtCursor (conf, it);

bool startsWithSrc = !elektraStrNCmp (keyName (cur), keyName (sourceKey), sourceNameLen - 1);
bool equalsSrc = !elektraStrCmp (keyName (cur), keyName (sourceKey));

// starts-with if recursive, or equals if !recursive
if ((recursive && startsWithSrc) || equalsSrc)
{
size_t newNameLen = destNameLen + (equalsSrc ? 0 : 1 + elektraStrLen (keyName (cur)) - sourceNameLen);
char * newName = elektraMalloc (newNameLen);
strcpy (newName, keyName (destKey));
if (!equalsSrc)
{
strcat (newName, "/");
strcat (newName, &keyName (cur)[sourceNameLen]);
}
CLI_PRINT (CLI_LOG_VERBOSE, "-> moving '%s' to '%s'\n", BOLD(keyName (cur)), BOLD(newName));
Key * tmpKey = keyDup (cur, KEY_CP_ALL);
keySetName (tmpKey, newName);
ksAppendKey (newConf, tmpKey);
elektraFree (newName);
count++;
}
ksAppendKey (newConf, cur);
}

if (kdbSet (handle, newConf, root) == -1)
{
ret = 1;
ELEKTRA_SET_VALIDATION_SEMANTIC_ERRORF (errorKey, "could not save keyset after moving: %s", GET_ERR (root));
}
CLI_PRINT (CLI_LOG_VERBOSE, "\nmoved %ld keys", count);


cleanup:
if (!noNewLine)
{
printf ("\n");
}
elektraFree ((void *) sourceName);
keyDel (root);
elektraFree ((void *) fmtBuffer);
ksDel (conf);
kdbClose (handle, errorKey);
return ret;
}
116 changes: 0 additions & 116 deletions src/tools/kdb/cp.cpp

This file was deleted.

36 changes: 36 additions & 0 deletions src/tools/kdb/cp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @file
*
* @brief Header for cp command
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*/

#ifndef ELEKTRA_KDB_CP_H
#define ELEKTRA_KDB_CP_H

#include <kdb.h>

/**
* Adds options specification of cp command to @spec
*
* @param spec the base spec where the commands spec should be added
*/
void addCpSpec (KeySet * spec);

/**
* Executes the cp command
*
* @param options cli options and arguments as specified in addCpSpec()
* @param errorKey key where errors and warnings should be saved
*
* @retval 0 cp command ran without errors
* @retval 1 errors occurred, keyGetMeta (errorKey, "error/reason") for info
*
*/
int execCp (KeySet * options, Key * errorKey);

// helper functions
int getKeyNameDepth (const char * name);

#endif // ELEKTRA_KDB_CP_H
47 changes: 0 additions & 47 deletions src/tools/kdb/cp.hpp

This file was deleted.

2 changes: 0 additions & 2 deletions src/tools/kdb/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <cache.hpp>
#include <complete.hpp>
#include <convert.hpp>
#include <cp.hpp>
#include <editor.hpp>
#include <export.hpp>
#include <file.hpp>
Expand Down Expand Up @@ -78,7 +77,6 @@ class Factory
// TODO: to add a new command, 2.) add a line here -> and you are done
m_factory.insert (std::make_pair ("cache", std::make_shared<Cnstancer<CacheCommand>> ()));
m_factory.insert (std::make_pair ("complete", std::make_shared<Cnstancer<CompleteCommand>> ()));
m_factory.insert (std::make_pair ("cp", std::make_shared<Cnstancer<CpCommand>> ()));
m_factory.insert (std::make_pair ("mount", std::make_shared<Cnstancer<MountCommand>> ()));
m_factory.insert (std::make_pair ("remount", std::make_shared<Cnstancer<RemountCommand>> ()));
m_factory.insert (std::make_pair ("shell", std::make_shared<Cnstancer<ShellCommand>> ()));
Expand Down
2 changes: 2 additions & 0 deletions src/tools/kdb/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <basename.h>
#include <cmerge.h>
#include <cp.h>
#include <dirname.h>
#include <get.h>
#include <ls.h>
Expand All @@ -33,6 +34,7 @@ extern char ** environ;
command subcommands[] = {
{ "basename", addBasenameSpec, execBasename },
{ "cmerge", addCmergeSpec, execCmerge },
{ "cp", addCpSpec, execCp },
{ "dirname", addDirnameSpec, execDirname },
{ "get", addGetSpec, execGet },
{ "ls", addLsSpec, execLs },
Expand Down

0 comments on commit 4f13f81

Please sign in to comment.