From 7fe5c0e8a84350c78f3753cf6ddd19e23d7f9903 Mon Sep 17 00:00:00 2001 From: theBreadCompany Date: Fri, 13 Jun 2025 04:03:21 +0200 Subject: [PATCH] refactor into separate libklist and cli helper --- src/CMakeLists.txt | 3 +- src/{main => cli}/CMakeLists.txt | 4 +- src/cli/include/process.h | 17 + src/cli/main.c | 222 +++++++++++++ src/cli/process.c | 262 +++++++++++++++ src/libklist/CMakeLists.txt | 3 + src/libklist/include/klist.h | 8 + src/{main => libklist}/include/models.h | 4 + src/{main => libklist}/include/sql.h | 0 src/{main => libklist}/include/util.h | 2 +- src/{main => libklist}/models.c | 48 +-- src/{main => libklist}/sql.c | 3 +- src/{main => libklist}/util.c | 36 ++- src/main/main.c | 403 ------------------------ 14 files changed, 576 insertions(+), 439 deletions(-) rename src/{main => cli}/CMakeLists.txt (55%) create mode 100644 src/cli/include/process.h create mode 100644 src/cli/main.c create mode 100644 src/cli/process.c create mode 100644 src/libklist/CMakeLists.txt create mode 100644 src/libklist/include/klist.h rename src/{main => libklist}/include/models.h (94%) rename src/{main => libklist}/include/sql.h (100%) rename src/{main => libklist}/include/util.h (100%) rename src/{main => libklist}/models.c (91%) rename src/{main => libklist}/sql.c (99%) rename src/{main => libklist}/util.c (76%) delete mode 100644 src/main/main.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1602825..e7bf0db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(main) \ No newline at end of file +add_subdirectory(cli) +add_subdirectory(libklist) \ No newline at end of file diff --git a/src/main/CMakeLists.txt b/src/cli/CMakeLists.txt similarity index 55% rename from src/main/CMakeLists.txt rename to src/cli/CMakeLists.txt index 4fd3609..5a1adc1 100644 --- a/src/main/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -1,4 +1,4 @@ -add_executable(klist main.c sql.c util.c models.c) +add_executable(klist main.c process.c) target_include_directories(klist PRIVATE include) -target_link_libraries(klist sqlite3) +target_link_libraries(klist libklist) target_compile_options(klist PRIVATE -Werror -Wall) #-Wextra) \ No newline at end of file diff --git a/src/cli/include/process.h b/src/cli/include/process.h new file mode 100644 index 0000000..0fa9a8b --- /dev/null +++ b/src/cli/include/process.h @@ -0,0 +1,17 @@ +#pragma once + +#include "klist.h" + +int klist_app_user_get(klist *); +int klist_app_user_create(klist *); +int klist_app_user_delete(klist *); + +int klist_app_list_add(klist *); +int klist_app_list_edit(klist *); +int klist_app_list_get(klist *); +int klist_app_list_delete(klist *); + +int klist_app_task_add(klist *); +int klist_app_task_edit(klist *); +int klist_app_task_get(klist *); +int klist_app_task_delete(klist *); \ No newline at end of file diff --git a/src/cli/main.c b/src/cli/main.c new file mode 100644 index 0000000..2d14d09 --- /dev/null +++ b/src/cli/main.c @@ -0,0 +1,222 @@ +#include +#include +#include +#include + +#include "process.h" +#include "util.h" + +void print_help(klist *ctx, char **argv); +void setup(klist *ctx, int argc, char **argv); + +int main(int argc, char **argv) { + klist *ctx = klist_init("test.db"); + + if (argc == 1) { + print_help(ctx, argv); + ctx->error = 1; + } + + if (!ctx->error) { + setup(ctx, argc, argv); + klist_user *user = klist_user_get_by_local(ctx, getuid()); + klist_list *list = NULL; + switch (ctx->cmd) { + case USER: + klist_user_context *user_ctx = ctx->cmd_ctx; + switch (user_ctx->cmd) { + case USER_GET: + klist_app_user_get(ctx); + break; + case USER_CREATE: + klist_app_user_create(ctx); + break; + case USER_DELETE: + klist_app_user_delete(ctx); + break; + } + klist_user_context_deinit(user_ctx); + break; + case LIST: + klist_list_context *list_ctx = ctx->cmd_ctx; + if (!list_ctx->name && list_ctx->cmd != LIST_GET) { + klist_print(ctx, KLIST_LOG_ERROR, "Missing name.\n"); + break; + } + switch (list_ctx->cmd) { + case LIST_ADD: + klist_app_list_add(ctx); + break; + case LIST_EDIT: + break; + case LIST_GET: + klist_app_list_get(ctx); + break; + case LIST_DELETE: + klist_app_list_delete(ctx); + } + if (list_ctx) + klist_list_context_deinit(list_ctx); + break; + case TASK: + klist_task_context *task_ctx = ctx->cmd_ctx; + switch (((klist_task_context *)ctx->cmd_ctx)->cmd) { + case TASK_ADD: // basically the same things happen and edit can create if + // nescessary + case TASK_EDIT: + klist_app_task_edit(ctx); + break; + case TASK_GET: + klist_app_task_get(ctx); + break; + case TASK_DELETE: + klist_app_task_delete(ctx); + } + klist_task_context_deinit(task_ctx); + default:; + } + if (list) + klist_list_deinit(list); + if (user) + klist_user_deinit(user); + } + + const int error = ctx->error; + klist_deinit(ctx); + return error; +} + +void print_help(klist *ctx, char **argv) { + printf("Usage: %s \n", argv[0]); +} + +void setup(klist *ctx, int argc, char **argv) { + if (strcmp(argv[1], "user") == 0) + ctx->cmd = USER; + else if (strcmp(argv[1], "list") == 0) + ctx->cmd = LIST; + else if (strcmp(argv[1], "task") == 0) + ctx->cmd = TASK; + else + print_help(ctx, argv); + + int opt; + switch (ctx->cmd) { + case USER: + optind = 2; + klist_user_context *user_ctx = klist_user_context_init(); + while ((opt = getopt(argc, argv, "cdg")) != -1) + switch (opt) { + case 'c': + user_ctx->cmd = USER_CREATE; + break; + case 'd': + user_ctx->cmd = USER_DELETE; + break; + case 'g': + user_ctx->cmd = USER_GET; + break; + default: + print_help(ctx, argv); + } + ctx->cmd_ctx = user_ctx; + break; + case LIST: + klist_list_context *list_ctx = klist_list_context_init(); + ctx->cmd_ctx = list_ctx; + if (argc < 3) { + list_ctx->cmd = LIST_GET; + break; + } + + optind = 2; + while ((opt = getopt(argc, argv, "aden:p:s:")) != -1) + switch (opt) { + case 'a': + list_ctx->cmd = LIST_ADD; + break; + case 'e': + list_ctx->cmd = LIST_EDIT; + break; + case 'd': + list_ctx->cmd = LIST_DELETE; + break; + case 'p': + list_ctx->preset = strdup(optarg); + break; + case 'n': + list_ctx->name = strdup(optarg); + break; + case 's': + char *stage = NULL; + while ((stage = strsep(&optarg, ","))) { + list_ctx->stages = realloc(list_ctx->stages, + (++list_ctx->stages_len) * sizeof(char *)); + list_ctx->stages[list_ctx->stages_len - 1] = strdup(stage); + } + break; + default: + print_help(ctx, argv); + klist_print( + ctx, KLIST_LOG_ERROR, + "" + "list options:\n" + "-a\t\tadd a list\n" + "-e\t\tedit a list\n" + "-d\t\tdelete a list\n" + "-p \tdefine as preset or use existing one with name " + "\n" + "Not providing a parameter prints all lists and existing " + "presets.\n\n"); + } + break; + case TASK: + if (argc < 3) { + klist_print(ctx, KLIST_LOG_ERROR, "Prints all lists.\n"); + break; + } + klist_task_context *task_ctx = klist_task_context_init(ctx); + + optind = 2; + + while ((opt = getopt(argc, argv, "aedl:n:s:")) != -1) + switch (opt) { + /*case 'a': + task_ctx->cmd = TASK_ADD; + break; + case 'e': + task_ctx->cmd = TASK_EDIT; + break;*/ + case 'd': + task_ctx->cmd = TASK_DELETE; + break; + case 'l': + task_ctx->list = strdup(optarg); + break; + case 'n': + task_ctx->name = strdup(optarg); + break; + case 's': + task_ctx->stage = strdup(optarg); + break; + default: + print_help(ctx, argv); + klist_print(ctx, KLIST_LOG_ERROR, + "" + "task options:" + "-a\tadd a task" + "-e\tedit a task" + "-d\tdelete a task" + "Not providing a parameter prints all tasks of a list."); + } + + if (task_ctx->cmd != TASK_DELETE) + task_ctx->cmd = TASK_ADD; + ctx->cmd_ctx = task_ctx; + break; + default: + klist_print(ctx, KLIST_LOG_ERROR, + "How did we land here?! Pls report argv[1] = %s\n", argv[1]); + print_help(ctx, argv); + } +} diff --git a/src/cli/process.c b/src/cli/process.c new file mode 100644 index 0000000..7865585 --- /dev/null +++ b/src/cli/process.c @@ -0,0 +1,262 @@ +#include "process.h" + +#include +#include +#include + +int klist_app_user_get(klist *ctx) { + klist_user *user = klist_user_get_by_local(ctx, getuid()); + + if (user) { + printf("User: %p\nID: %lu\n", user->name, user->id); + size_t lists_len = 0; + klist_list **lists = klist_list_get_all_by_user(ctx, user->id, &lists_len); + printf("Lists: %lu\n", lists_len); + int i = 0; + for (; i < lists_len; i++) + klist_list_deinit(lists[i]); + } else + klist_print(ctx, KLIST_LOG_ERROR, "No user for '%s' found.\n", getlogin()); + return 0; +} + +int klist_app_user_create(klist *ctx) { + klist_print(ctx, KLIST_LOG_INFO, + (klist_assure_user(ctx, getuid(), getlogin())) + ? "User created.\n" + : "User already exists.\n"); + return 0; +} + +int klist_app_user_delete(klist *ctx) { + klist_user *user = klist_user_get_by_local(ctx, getuid()); + if (user) { + klist_user_delete(ctx, user); + printf("User deleted.\n"); + } else + klist_print(ctx, KLIST_LOG_ERROR, "User not found, no changes done.\n"); + return 0; +} + +int klist_app_list_add(klist *ctx) { + klist_list_context *list_ctx = ctx->cmd_ctx; + if (!list_ctx->stages_len) { + klist_print(ctx, KLIST_LOG_ERROR, "Missing stages.\n"); + return 1; + } + klist_assure_user(ctx, getuid(), getlogin()); + klist_user *user = klist_user_get_by_local(ctx, getuid()); + klist_list *list = + klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); + if (!list) + list = klist_list_init(); + list->name = (unsigned char *)strdup(list_ctx->name); + if (list->desc) + list->desc = (unsigned char *)strdup(list_ctx->desc); + list->is_preset = false; + klist_list_save(ctx, list, user); + int i = 0; + for (; i < list_ctx->stages_len; i++) { + klist_stage *stage = klist_stage_init(); + stage->name = (unsigned char *)strdup(list_ctx->stages[i]); + stage->list_id = list->id; + klist_stage_save(ctx, stage); + klist_stage_deinit(stage); + } + return 0; +} + +int klist_app_list_edit(klist *ctx) { + klist_print(ctx, KLIST_LOG_ERROR, "Not implemented\n"); + return 0; +} + +int klist_app_list_get(klist *ctx) { + klist_list_context *list_ctx = ctx->cmd_ctx; + klist_user *user = klist_user_get_by_local(ctx, getuid()); + + size_t lists_len = 0; + klist_list **lists = NULL; + if (list_ctx->name) { + klist_list *list = + klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); + if (list) { + lists_len = 1; + lists = malloc(lists_len * sizeof(klist_list)); + memcpy(lists[0], list, sizeof(klist_list)); + klist_list_deinit(list); + }; + } else + lists = klist_list_get_all_by_user(ctx, user->id, &lists_len); + + if (lists_len) { + int i = 0; + for (; i < lists_len; i++) { + klist_list *list = lists[i]; + size_t tasks_len = 0; + klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); + printf("Name: %s\n", (char *)list->name); + printf("Description: %s\n", list->desc ? (char *)list->desc : "N/A"); + printf("Tasks: %ld\n", tasks_len); + i = 0; + for (; i < tasks_len; i++) + klist_task_deinit(tasks[i]); + free(tasks); + klist_list_deinit(list); + } + free(lists); + } else if (list_ctx->name) + klist_print(ctx, KLIST_LOG_ERROR, "List '%s' not found.\n", list_ctx->name); + else + klist_print(ctx, KLIST_LOG_WARNING, "No lists found.\n"); + return 0; +} + +int klist_app_list_delete(klist *ctx) { + klist_list_context *list_ctx = ctx->cmd_ctx; + klist_assure_user(ctx, getuid(), getlogin()); + klist_user *user = klist_user_get_by_local(ctx, getuid()); + klist_list *list = + klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); + + list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); + if (list) { + size_t tasks_len = 0; + klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); + int i = 0; + for (; i < tasks_len; i++) { + klist_task_delete(ctx, tasks[i]); + klist_task_deinit(tasks[i]); + } + free(tasks); + } + return 0; +} + +int klist_app_task_add(klist *ctx) { return klist_app_task_edit(ctx); } + +int klist_app_task_edit(klist *ctx) { + klist_task_context *task_ctx = ctx->cmd_ctx; + klist_user *user = klist_user_get_by_local(ctx, getuid()); + klist_list *list = NULL; + + klist_assure_user(ctx, getuid(), getlogin()); + list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); + if (list) { + size_t stages_len = 0; + klist_stage **stages = + klist_stage_get_all_for_list(ctx, list->id, &stages_len); + if (!task_ctx->stage) { + klist_print(ctx, KLIST_LOG_ERROR, + "Stage missing/wrong, please pass one of: "); + int i = 0; + for (; i < stages_len; i++) + fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); + fprintf(ctx->log_target, "\n"); + return 1; + } + int i = 0; + ssize_t stage_id = -1; + for (; i < stages_len; i++) + if (strcmp((char *)stages[i]->name, task_ctx->stage) == 0) + stage_id = stages[i]->id; + + if (stage_id == -1) { + klist_print(ctx, KLIST_LOG_ERROR, + "Stage %s not found. Use one of: ", task_ctx->stage); + int i = 0; + for (; i < stages_len; i++) + fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); + fprintf(ctx->log_target, "\n"); + } + i = 0; + for (; i < stages_len; i++) + klist_stage_deinit(stages[i]); + free(stages); + if (ctx->error) + return ctx->error; + + klist_task *task = + klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); + if (!task) + task = klist_task_init(); + if (task->name) + free(task->name); + task->name = (unsigned char *)strdup(task_ctx->name); + if (task->desc) + free(task->desc); + if (task_ctx->desc) + task->desc = (unsigned char *)strdup(task_ctx->desc); + task->stage_id = stage_id; + klist_task_save(ctx, task); + klist_task_deinit(task); + } else + klist_print(ctx, KLIST_LOG_ERROR, "List not found.\n"); + return 0; +} + +int klist_app_task_get(klist *ctx) { + klist_task_context *task_ctx = ctx->cmd_ctx; + klist_assure_user(ctx, getuid(), getlogin()); + klist_user *user = klist_user_get_by_local(ctx, getuid()); + klist_list *list = + klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); + if (list) { + if (task_ctx->name) { + klist_task *task = + klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); + if (task) { + printf("Name: %s\n", (char *)task->name); + printf("Description: %s\n", task->desc ? (char *)task->desc : "N/A"); + klist_stage *stage = klist_stage_get_by_id(ctx, task->stage_id); + printf("Stage: %s\n", (char *)stage->name); + klist_stage_deinit(stage); + klist_task_deinit(task); + } else + klist_print(ctx, KLIST_LOG_ERROR, "Task not found.\n"); + } else { + size_t tasks_len = 0; + klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); + int i = 0; + for (; i < tasks_len; i++) { + printf("Name: %s\n", (char *)tasks[i]->name); + printf("Description: %s\n", + tasks[i]->desc ? (char *)tasks[i]->desc : "N/A"); + klist_stage *stage = klist_stage_get_by_id(ctx, tasks[i]->stage_id); + printf("Stage: %s\n", (char *)stage->name); + klist_stage_deinit(stage); + klist_task_deinit(tasks[i]); + if ((i + 1) < tasks_len) + fprintf(ctx->log_target, "\n"); + } + } + } else + klist_print(ctx, KLIST_LOG_ERROR, "list not found\n"); + return 0; +} + +int klist_app_task_delete(klist *ctx) { + klist_task_context *task_ctx = ctx->cmd_ctx; + klist_assure_user(ctx, getuid(), getlogin()); + klist_user *user = klist_user_get_by_local(ctx, getuid()); + klist_list *list = + klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); + if (list) { + if (task_ctx) { + klist_task *task = + klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); + if (task) { + klist_print(ctx, KLIST_LOG_WARNING, "Deleting task '%s'.\n", + (char *)task->name); + klist_task_delete(ctx, task); + klist_task_deinit(task); + } else + klist_print(ctx, KLIST_LOG_ERROR, "Task not found.\n"); + } else + klist_print(ctx, KLIST_LOG_ERROR, + "Task not found, only deletion by name is " + "currently supoprted.\n"); + } else + klist_print(ctx, KLIST_LOG_ERROR, "Not implemented\n"); + return 0; +} \ No newline at end of file diff --git a/src/libklist/CMakeLists.txt b/src/libklist/CMakeLists.txt new file mode 100644 index 0000000..8f14047 --- /dev/null +++ b/src/libklist/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(libklist models.c sql.c util.c) +target_include_directories(libklist PUBLIC include) +target_link_libraries(libklist sqlite3) \ No newline at end of file diff --git a/src/libklist/include/klist.h b/src/libklist/include/klist.h new file mode 100644 index 0000000..12e7394 --- /dev/null +++ b/src/libklist/include/klist.h @@ -0,0 +1,8 @@ +#ifndef KLIST_H +#define KLIST_H + +#include "models.h" +#include "sql.h" +#include "util.h" + +#endif \ No newline at end of file diff --git a/src/main/include/models.h b/src/libklist/include/models.h similarity index 94% rename from src/main/include/models.h rename to src/libklist/include/models.h index e5714b4..6545033 100644 --- a/src/main/include/models.h +++ b/src/libklist/include/models.h @@ -72,3 +72,7 @@ klist_task *klist_task_get_for_list_by_name(const klist *, u_int, const char *); void klist_task_save(const klist *, klist_task *); void klist_task_delete(const klist *, const klist_task *); void klist_task_deinit(klist_task *); + +void klist_print_user(klist *, klist_user *); +void klist_print_list(klist *, klist_list *); +void klist_print_task(klist *, klist_task *); \ No newline at end of file diff --git a/src/main/include/sql.h b/src/libklist/include/sql.h similarity index 100% rename from src/main/include/sql.h rename to src/libklist/include/sql.h diff --git a/src/main/include/util.h b/src/libklist/include/util.h similarity index 100% rename from src/main/include/util.h rename to src/libklist/include/util.h index 198f9f0..867608f 100644 --- a/src/main/include/util.h +++ b/src/libklist/include/util.h @@ -1,8 +1,8 @@ #pragma once #include #include -#include #include +#include /* * command parsing diff --git a/src/main/models.c b/src/libklist/models.c similarity index 91% rename from src/main/models.c rename to src/libklist/models.c index 72c1b3c..892303f 100644 --- a/src/main/models.c +++ b/src/libklist/models.c @@ -1,9 +1,10 @@ -#include "models.h" +#include #include #include #include +#include "klist.h" #include "sql.h" klist_user *klist_user_init() { @@ -39,8 +40,8 @@ klist_user *klist_user_get_by_local(const klist *ctx, u_int local_id) { if (sqlite3_step(stmt) == SQLITE_ROW) { user = klist_user_init_from_sql(stmt); } else - klist_print(ctx, KLIST_LOG_ERROR, "failed to get user by local id %u: %s\n", local_id, - sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, "failed to get user by local id %u: %s\n", + local_id, sqlite3_errmsg(ctx->db)); sqlite3_reset(stmt); return user; @@ -56,8 +57,8 @@ void klist_user_save(const klist *ctx, klist_user *user) { if ((result = sqlite3_step(stmt)) == SQLITE_ROW) user->id = sqlite3_column_int(stmt, 0); else - klist_print(ctx, KLIST_LOG_ERROR, "failed to save user: %s - %d\n", sqlite3_errmsg(ctx->db), - result); + klist_print(ctx, KLIST_LOG_ERROR, "failed to save user: %s - %d\n", + sqlite3_errmsg(ctx->db), result); sqlite3_reset(stmt); if (user->local_id != -1) { @@ -65,11 +66,13 @@ void klist_user_save(const klist *ctx, klist_user *user) { sqlite3_bind_int(stmt, 1, user->id); sqlite3_bind_int(stmt, 2, user->local_id); if (sqlite3_step(stmt) != SQLITE_ROW) - klist_print(ctx, KLIST_LOG_ERROR, "failed to save logins for user: %s - %d\n", - sqlite3_errmsg(ctx->db), result); + klist_print(ctx, KLIST_LOG_ERROR, + "failed to save logins for user: %s - %d\n", + sqlite3_errmsg(ctx->db), result); sqlite3_reset(stmt); } else - klist_print(ctx, KLIST_LOG_ERROR, "no local uid saved for user %s", (char *)user->name); + klist_print(ctx, KLIST_LOG_ERROR, "no local uid saved for user %s", + (char *)user->name); } void klist_user_delete(const klist *ctx, const klist_user *user) { @@ -145,8 +148,8 @@ void klist_stage_save(const klist *ctx, klist_stage *stage) { stage->id = sqlite3_column_int(stmt, 0); sqlite3_reset(stmt); } else - klist_print(ctx, KLIST_LOG_ERROR, "failed to save stage: %s - %d\n", sqlite3_errmsg(ctx->db), - result); + klist_print(ctx, KLIST_LOG_ERROR, "failed to save stage: %s - %d\n", + sqlite3_errmsg(ctx->db), result); } void klist_stage_deinit(klist_stage *stage) { @@ -216,7 +219,8 @@ klist_list *klist_list_get_by_user_and_name(const klist *ctx, u_int user_id, if (sqlite3_step(stmt) == SQLITE_ROW) list = klist_list_init_from_sql(stmt); else - klist_print(ctx, KLIST_LOG_ERROR, "failed to get lists for user: %s\n", sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, "failed to get lists for user: %s\n", + sqlite3_errmsg(ctx->db)); sqlite3_reset(stmt); return list; } @@ -233,11 +237,10 @@ void klist_list_save(const klist *ctx, klist_list *list, if ((result = sqlite3_step(stmt)) == SQLITE_ROW) list->id = sqlite3_column_int(stmt, 0); else - klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), - result); + klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", + sqlite3_errmsg(ctx->db), result); sqlite3_reset(stmt); - if (list->id > -1) { stmt = ctx->stmts[ADD_USER_LIST]; sqlite3_bind_int(stmt, 1, list->id); @@ -245,8 +248,9 @@ void klist_list_save(const klist *ctx, klist_list *list, if (sqlite3_step(stmt) == SQLITE_DONE) sqlite3_reset(stmt); else - klist_print(ctx, KLIST_LOG_ERROR, "failed to save user - list relation in join table: %s\n", - sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, + "failed to save user - list relation in join table: %s\n", + sqlite3_errmsg(ctx->db)); } } @@ -319,8 +323,9 @@ klist_task *klist_task_get_for_list_by_name(const klist *ctx, u_int list_id, if (sqlite3_step(stmt) == SQLITE_ROW) task = klist_task_init_from_sql(stmt); else - klist_print(ctx, KLIST_LOG_WARNING, "no tasks found for list %d, name '%s': %s\n", list_id, - name, sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_WARNING, + "no tasks found for list %d, name '%s': %s\n", list_id, name, + sqlite3_errmsg(ctx->db)); sqlite3_reset(stmt); return task; } @@ -340,8 +345,8 @@ void klist_task_save(const klist *ctx, klist_task *task) { if ((result = sqlite3_step(stmt)) == SQLITE_ROW) { task->id = sqlite3_column_int(stmt, 0); } else - klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), - result); + klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", + sqlite3_errmsg(ctx->db), result); sqlite3_reset(stmt); } void klist_task_delete(const klist *ctx, const klist_task *task) { @@ -350,7 +355,8 @@ void klist_task_delete(const klist *ctx, const klist_task *task) { if (sqlite3_step(stmt) == SQLITE_DONE) sqlite3_reset(stmt); else - klist_print(ctx, KLIST_LOG_ERROR, "failed to delete task: %s\n", sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, "failed to delete task: %s\n", + sqlite3_errmsg(ctx->db)); } void klist_task_deinit(klist_task *task) { diff --git a/src/main/sql.c b/src/libklist/sql.c similarity index 99% rename from src/main/sql.c rename to src/libklist/sql.c index 07506b0..13238a4 100644 --- a/src/main/sql.c +++ b/src/libklist/sql.c @@ -63,7 +63,8 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { return "select users.*, user_logins.local_id from users inner join " "user_logins on user_logins.user_id = users.id where users.id = ?1"; case GET_USER_BY_LOCAL: - return "select users.* from users inner join user_logins on user_logins.user_id " + return "select users.* from users inner join user_logins on " + "user_logins.user_id " "= users.id where user_logins.local_id = ?1"; case GET_USERS: return "select * from users"; diff --git a/src/main/util.c b/src/libklist/util.c similarity index 76% rename from src/main/util.c rename to src/libklist/util.c index a15d9b7..8fb14ef 100644 --- a/src/main/util.c +++ b/src/libklist/util.c @@ -97,23 +97,30 @@ void klist_task_context_deinit(klist_task_context *ctx) { */ void klist_sql_prepare(klist *ctx, char *db) { - if (!db) klist_print(ctx, KLIST_LOG_WARNING, "Database will be in-memory only, changes are not persistent!\n"); + if (!db) + klist_print( + ctx, KLIST_LOG_WARNING, + "Database will be in-memory only, changes are not persistent!\n"); if (sqlite3_open(db ? db : ":memory:", &ctx->db) != SQLITE_OK) { - klist_print(ctx, KLIST_LOG_ERROR, "Can't open database: %s\n", sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, "Can't open database: %s\n", + sqlite3_errmsg(ctx->db)); return; } char *errmsg = NULL; sqlite3_exec(ctx->db, klist_sql_get(INIT), NULL, NULL, &errmsg); if (errmsg) { - klist_print(ctx, KLIST_LOG_ERROR, "Database initialization failed (%s), expect issues.\n", - sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, + "Database initialization failed (%s), expect issues.\n", + sqlite3_errmsg(ctx->db)); sqlite3_free(errmsg); } int i = 0; for (; i < _KLIST_SQL_COUNT; i++) if (sqlite3_prepare(ctx->db, klist_sql_get(i), -1, &ctx->stmts[i], NULL) != SQLITE_OK) - klist_print(ctx, KLIST_LOG_WARNING, "sqlite3_prepare for '%s' failed: %s\n", klist_sql_get(i), sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_WARNING, + "sqlite3_prepare for '%s' failed: %s\n", klist_sql_get(i), + sqlite3_errmsg(ctx->db)); } void klist_sql_seed(klist *ctx) {} @@ -143,13 +150,22 @@ void klist_assure_task(klist *, char *); * printing methods */ -void klist_print(const klist *ctx, KLIST_LOG_LEVEL log_level, const char *format, ...) { +void klist_print(const klist *ctx, KLIST_LOG_LEVEL log_level, + const char *format, ...) { if (ctx->log_level >= log_level) { switch (log_level) { - case KLIST_LOG_DEBUG: fprintf(ctx->log_target, "[\x1B[34mDBG\x1B[0m] "); break; - case KLIST_LOG_INFO: fprintf(ctx->log_target, "[\x1B[36mINF\x1B[0m] "); break; - case KLIST_LOG_WARNING: fprintf(ctx->log_target, "[\x1B[33mWRN\x1B[0m] "); break; - case KLIST_LOG_ERROR: fprintf(ctx->log_target, "[\x1B[31mERR\x1B[0m] "); break; + case KLIST_LOG_DEBUG: + fprintf(ctx->log_target, "[\x1B[34mDBG\x1B[0m] "); + break; + case KLIST_LOG_INFO: + fprintf(ctx->log_target, "[\x1B[36mINF\x1B[0m] "); + break; + case KLIST_LOG_WARNING: + fprintf(ctx->log_target, "[\x1B[33mWRN\x1B[0m] "); + break; + case KLIST_LOG_ERROR: + fprintf(ctx->log_target, "[\x1B[31mERR\x1B[0m] "); + break; } va_list args; va_start(args, format); diff --git a/src/main/main.c b/src/main/main.c deleted file mode 100644 index 016a33a..0000000 --- a/src/main/main.c +++ /dev/null @@ -1,403 +0,0 @@ -#include -#include -#include -#include - -#include "models.h" -#include "util.h" - -void print_help(klist *ctx, char **argv); -void setup(klist *ctx, int argc, char **argv); - -int main(int argc, char **argv) { - klist *ctx = klist_init("test.db"); - - if (argc == 1) { - print_help(ctx, argv); - ctx->error = 1; - } - - if (!ctx->error) { - setup(ctx, argc, argv); - klist_user *user = klist_user_get_by_local(ctx, getuid()); - klist_list *list = NULL; - int i = 0; - switch (ctx->cmd) { - case USER: - klist_user_context *user_ctx = ctx->cmd_ctx; - switch (user_ctx->cmd) { - case USER_GET: - if (user) { - printf("User: %p\nID: %lu\n", user->name, user->id); - size_t lists_len = 0; - klist_list **lists = - klist_list_get_all_by_user(ctx, user->id, &lists_len); - printf("Lists: %lu\n", lists_len); - for (; i < lists_len; i++) - klist_list_deinit(lists[i]); - } else - klist_print(ctx, KLIST_LOG_ERROR, "No user for '%s' found.\n", getlogin()); - break; - case USER_CREATE: - klist_print(ctx, KLIST_LOG_INFO, (klist_assure_user(ctx, getuid(), getlogin())) - ? "User created.\n" - : "User already exists.\n"); - break; - case USER_DELETE: - if (user) { - klist_user_delete(ctx, user); - printf("User deleted.\n"); - } else - klist_print(ctx, KLIST_LOG_ERROR, "User not found, no changes done.\n"); - break; - } - klist_user_context_deinit(user_ctx); - break; - case LIST: - klist_list_context *list_ctx = ctx->cmd_ctx; - if (!list_ctx->name && list_ctx->cmd != LIST_GET) { - klist_print(ctx, KLIST_LOG_ERROR, "Missing name.\n"); - break; - } - switch (list_ctx->cmd) { - case LIST_ADD: - if (!list_ctx->stages_len) { - klist_print(ctx, KLIST_LOG_ERROR, "Missing stages.\n"); - break; - } - klist_assure_user(ctx, getuid(), getlogin()); - list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); - if (!list) - list = klist_list_init(); - list->name = (unsigned char *)strdup(list_ctx->name); - if (list->desc) - list->desc = (unsigned char *)strdup(list_ctx->desc); - list->is_preset = false; - klist_list_save(ctx, list, user); - i = 0; - for (; i < list_ctx->stages_len; i++) { - klist_stage *stage = klist_stage_init(); - stage->name = (unsigned char *)strdup(list_ctx->stages[i]); - stage->list_id = list->id; - klist_stage_save(ctx, stage); - klist_stage_deinit(stage); - } - break; - case LIST_EDIT: - klist_print(ctx, KLIST_LOG_ERROR, "Not implemented\n"); - break; - case LIST_GET: - size_t lists_len = 0; - klist_list **lists = NULL; - if (list_ctx->name) { - klist_list *list = - klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); - if (list) { - lists_len = 1; - lists = malloc(lists_len * sizeof(klist_list)); - memcpy(lists[0], list, sizeof(klist_list)); - klist_list_deinit(list); - }; - } else - lists = klist_list_get_all_by_user(ctx, user->id, &lists_len); - - if (lists_len) { - i = 0; - for (; i < lists_len; i++) { - klist_list *list = lists[i]; - size_t tasks_len = 0; - klist_task **tasks = - klist_task_get_for_list(ctx, list->id, &tasks_len); - printf("Name: %s\n", (char *)list->name); - printf("Description: %s\n", list->desc ? (char *)list->desc : "N/A"); - printf("Tasks: %ld\n", tasks_len); - i = 0; - for (; i < tasks_len; i++) - klist_task_deinit(tasks[i]); - free(tasks); - klist_list_deinit(list); - } - free(lists); - } else if (list_ctx->name) - klist_print(ctx, KLIST_LOG_ERROR, "List '%s' not found.\n", list_ctx->name); - else - klist_print(ctx, KLIST_LOG_WARNING, "No lists found.\n"); - break; - case LIST_DELETE: - list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); - if (list) { - size_t tasks_len = 0; - klist_task **tasks = - klist_task_get_for_list(ctx, list->id, &tasks_len); - i = 0; - for (; i < tasks_len; i++) { - klist_task_delete(ctx, tasks[i]); - klist_task_deinit(tasks[i]); - } - free(tasks); - } - } - if (list_ctx) - klist_list_context_deinit(list_ctx); - break; - case TASK: - klist_task_context *task_ctx = ctx->cmd_ctx; - switch (((klist_task_context *)ctx->cmd_ctx)->cmd) { - case TASK_ADD: // basically the same things happen and edit can create if - // nescessary - case TASK_EDIT: - klist_assure_user(ctx, getuid(), getlogin()); - list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); - if (list) { - size_t stages_len = 0; - klist_stage **stages = - klist_stage_get_all_for_list(ctx, list->id, &stages_len); - if (!task_ctx->stage) { - klist_print(ctx, KLIST_LOG_ERROR, "Stage missing/wrong, please pass one of: "); - i = 0; - for (; i < stages_len; i++) - fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); - fprintf(ctx->log_target, "\n"); - break; - } - i = 0; - ssize_t stage_id = -1; - for (; i < stages_len; i++) - if (strcmp((char *)stages[i]->name, task_ctx->stage) == 0) - stage_id = stages[i]->id; - - if (stage_id == -1) { - klist_print(ctx, KLIST_LOG_ERROR, - "Stage %s not found. Use one of: ", task_ctx->stage); - i = 0; - for (; i < stages_len; i++) - fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); - fprintf(ctx->log_target, "\n"); - } - i = 0; - for (; i < stages_len; i++) - klist_stage_deinit(stages[i]); - free(stages); - if (ctx->error) - break; - - klist_task *task = - klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); - if (!task) - task = klist_task_init(); - if (task->name) - free(task->name); - task->name = (unsigned char *)strdup(task_ctx->name); - if (task->desc) - free(task->desc); - if (task_ctx->desc) - task->desc = (unsigned char *)strdup(task_ctx->desc); - task->stage_id = stage_id; - klist_task_save(ctx, task); - klist_task_deinit(task); - } else - klist_print(ctx, KLIST_LOG_ERROR, "List not found.\n"); - break; - case TASK_GET: - klist_assure_user(ctx, getuid(), getlogin()); - user = klist_user_get_by_local(ctx, getuid()); - list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); - if (list) { - if (task_ctx->name) { - klist_task *task = - klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); - if (task) { - printf("Name: %s\n", (char *)task->name); - printf("Description: %s\n", task->desc ? (char *)task->desc : "N/A"); - klist_stage *stage = klist_stage_get_by_id(ctx, task->stage_id); - printf("Stage: %s\n", (char *)stage->name); - klist_stage_deinit(stage); - klist_task_deinit(task); - } else - klist_print(ctx, KLIST_LOG_ERROR, "Task not found.\n"); - } else { - size_t tasks_len = 0; - klist_task **tasks = - klist_task_get_for_list(ctx, list->id, &tasks_len); - i = 0; - for (; i < tasks_len; i++) { - printf("Name: %s\n", (char *)tasks[i]->name); - printf("Description: %s\n", tasks[i]->desc ? (char *)tasks[i]->desc : "N/A"); - klist_stage *stage = - klist_stage_get_by_id(ctx, tasks[i]->stage_id); - printf("Stage: %s\n", (char *)stage->name); - klist_stage_deinit(stage); - klist_task_deinit(tasks[i]); - if ((i + 1) < tasks_len) - fprintf(ctx->log_target, "\n"); - } - } - } else - klist_print(ctx, KLIST_LOG_ERROR, "list not found\n"); - case TASK_DELETE: - klist_assure_user(ctx, getuid(), getlogin()); - user = klist_user_get_by_local(ctx, getuid()); - list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); - if (list) { - if (task_ctx) { - klist_task *task = - klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); - if (task) { - klist_print(ctx, KLIST_LOG_WARNING, "Deleting task '%s'.\n", (char *)task->name); - klist_task_delete(ctx, task); - klist_task_deinit(task); - } else - klist_print(ctx, KLIST_LOG_ERROR, "Task not found.\n"); - } else - klist_print(ctx, KLIST_LOG_ERROR, "Task not found, only deletion by name is " - "currently supoprted.\n"); - } else - klist_print(ctx, KLIST_LOG_ERROR, "Not implemented\n"); - } - klist_task_context_deinit(task_ctx); - default:; - } - if (list) - klist_list_deinit(list); - if (user) - klist_user_deinit(user); - } - - const int error = ctx->error; - klist_deinit(ctx); - return error; -} - -void print_help(klist *ctx, char **argv) { - printf("Usage: %s \n", argv[0]); -} - -void setup(klist *ctx, int argc, char **argv) { - if (strcmp(argv[1], "user") == 0) - ctx->cmd = USER; - else if (strcmp(argv[1], "list") == 0) - ctx->cmd = LIST; - else if (strcmp(argv[1], "task") == 0) - ctx->cmd = TASK; - else - print_help(ctx, argv); - - int opt; - switch (ctx->cmd) { - case USER: - optind = 2; - klist_user_context *user_ctx = klist_user_context_init(); - while ((opt = getopt(argc, argv, "cdg")) != -1) - switch (opt) { - case 'c': - user_ctx->cmd = USER_CREATE; - break; - case 'd': - user_ctx->cmd = USER_DELETE; - break; - case 'g': - user_ctx->cmd = USER_GET; - break; - default: - print_help(ctx, argv); - } - ctx->cmd_ctx = user_ctx; - break; - case LIST: - klist_list_context *list_ctx = klist_list_context_init(); - ctx->cmd_ctx = list_ctx; - if (argc < 3) { - list_ctx->cmd = LIST_GET; - break; - } - - optind = 2; - while ((opt = getopt(argc, argv, "aden:p:s:")) != -1) - switch (opt) { - case 'a': - list_ctx->cmd = LIST_ADD; - break; - case 'e': - list_ctx->cmd = LIST_EDIT; - break; - case 'd': - list_ctx->cmd = LIST_DELETE; - break; - case 'p': - list_ctx->preset = strdup(optarg); - break; - case 'n': - list_ctx->name = strdup(optarg); - break; - case 's': - char *stage = NULL; - while ((stage = strsep(&optarg, ","))) { - list_ctx->stages = realloc(list_ctx->stages, - (++list_ctx->stages_len) * sizeof(char *)); - list_ctx->stages[list_ctx->stages_len - 1] = strdup(stage); - } - break; - default: - print_help(ctx, argv); - klist_print(ctx, KLIST_LOG_ERROR, - "" - "list options:\n" - "-a\t\tadd a list\n" - "-e\t\tedit a list\n" - "-d\t\tdelete a list\n" - "-p \tdefine as preset or use existing one with name " - "\n" - "Not providing a parameter prints all lists and existing " - "presets.\n\n"); - } - break; - case TASK: - if (argc < 3) { - klist_print(ctx, KLIST_LOG_ERROR, "Prints all lists.\n"); - break; - } - klist_task_context *task_ctx = klist_task_context_init(ctx); - - optind = 2; - - while ((opt = getopt(argc, argv, "aedl:n:s:")) != -1) - switch (opt) { - /*case 'a': - task_ctx->cmd = TASK_ADD; - break; - case 'e': - task_ctx->cmd = TASK_EDIT; - break;*/ - case 'd': - task_ctx->cmd = TASK_DELETE; - break; - case 'l': - task_ctx->list = strdup(optarg); - break; - case 'n': - task_ctx->name = strdup(optarg); - break; - case 's': - task_ctx->stage = strdup(optarg); - break; - default: - print_help(ctx, argv); - klist_print(ctx, KLIST_LOG_ERROR, - "" - "task options:" - "-a\tadd a task" - "-e\tedit a task" - "-d\tdelete a task" - "Not providing a parameter prints all tasks of a list."); - } - - if (task_ctx->cmd != TASK_DELETE) - task_ctx->cmd = TASK_ADD; - ctx->cmd_ctx = task_ctx; - break; - default: - klist_print(ctx, KLIST_LOG_ERROR, "How did we land here?! Pls report argv[1] = %s\n", - argv[1]); - print_help(ctx, argv); - } -}