refactor into separate libklist and cli helper

This commit is contained in:
theBreadCompany 2025-06-13 04:03:21 +02:00
parent 89b7f484f7
commit 7fe5c0e8a8
14 changed files with 576 additions and 439 deletions

View file

@ -1 +1,2 @@
add_subdirectory(main) add_subdirectory(cli)
add_subdirectory(libklist)

View file

@ -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_include_directories(klist PRIVATE include)
target_link_libraries(klist sqlite3) target_link_libraries(klist libklist)
target_compile_options(klist PRIVATE -Werror -Wall) #-Wextra) target_compile_options(klist PRIVATE -Werror -Wall) #-Wextra)

17
src/cli/include/process.h Normal file
View file

@ -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 *);

222
src/cli/main.c Normal file
View file

@ -0,0 +1,222 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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 <action>\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 <preset>\tdefine as preset or use existing one with name "
"<preset>\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);
}
}

262
src/cli/process.c Normal file
View file

@ -0,0 +1,262 @@
#include "process.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
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;
}

View file

@ -0,0 +1,3 @@
add_library(libklist models.c sql.c util.c)
target_include_directories(libklist PUBLIC include)
target_link_libraries(libklist sqlite3)

View file

@ -0,0 +1,8 @@
#ifndef KLIST_H
#define KLIST_H
#include "models.h"
#include "sql.h"
#include "util.h"
#endif

View file

@ -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_save(const klist *, klist_task *);
void klist_task_delete(const klist *, const klist_task *); void klist_task_delete(const klist *, const klist_task *);
void klist_task_deinit(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 *);

View file

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <sqlite3.h> #include <sqlite3.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h>
/* /*
* command parsing * command parsing

View file

@ -1,9 +1,10 @@
#include "models.h"
#include <sqlite3.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "klist.h"
#include "sql.h" #include "sql.h"
klist_user *klist_user_init() { 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) { if (sqlite3_step(stmt) == SQLITE_ROW) {
user = klist_user_init_from_sql(stmt); user = klist_user_init_from_sql(stmt);
} else } else
klist_print(ctx, KLIST_LOG_ERROR, "failed to get user by local id %u: %s\n", local_id, klist_print(ctx, KLIST_LOG_ERROR, "failed to get user by local id %u: %s\n",
sqlite3_errmsg(ctx->db)); local_id, sqlite3_errmsg(ctx->db));
sqlite3_reset(stmt); sqlite3_reset(stmt);
return user; return user;
@ -56,8 +57,8 @@ void klist_user_save(const klist *ctx, klist_user *user) {
if ((result = sqlite3_step(stmt)) == SQLITE_ROW) if ((result = sqlite3_step(stmt)) == SQLITE_ROW)
user->id = sqlite3_column_int(stmt, 0); user->id = sqlite3_column_int(stmt, 0);
else else
klist_print(ctx, KLIST_LOG_ERROR, "failed to save user: %s - %d\n", sqlite3_errmsg(ctx->db), klist_print(ctx, KLIST_LOG_ERROR, "failed to save user: %s - %d\n",
result); sqlite3_errmsg(ctx->db), result);
sqlite3_reset(stmt); sqlite3_reset(stmt);
if (user->local_id != -1) { 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, 1, user->id);
sqlite3_bind_int(stmt, 2, user->local_id); sqlite3_bind_int(stmt, 2, user->local_id);
if (sqlite3_step(stmt) != SQLITE_ROW) if (sqlite3_step(stmt) != SQLITE_ROW)
klist_print(ctx, KLIST_LOG_ERROR, "failed to save logins for user: %s - %d\n", klist_print(ctx, KLIST_LOG_ERROR,
sqlite3_errmsg(ctx->db), result); "failed to save logins for user: %s - %d\n",
sqlite3_errmsg(ctx->db), result);
sqlite3_reset(stmt); sqlite3_reset(stmt);
} else } 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) { 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); stage->id = sqlite3_column_int(stmt, 0);
sqlite3_reset(stmt); sqlite3_reset(stmt);
} else } else
klist_print(ctx, KLIST_LOG_ERROR, "failed to save stage: %s - %d\n", sqlite3_errmsg(ctx->db), klist_print(ctx, KLIST_LOG_ERROR, "failed to save stage: %s - %d\n",
result); sqlite3_errmsg(ctx->db), result);
} }
void klist_stage_deinit(klist_stage *stage) { 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) if (sqlite3_step(stmt) == SQLITE_ROW)
list = klist_list_init_from_sql(stmt); list = klist_list_init_from_sql(stmt);
else 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); sqlite3_reset(stmt);
return list; return list;
} }
@ -233,11 +237,10 @@ void klist_list_save(const klist *ctx, klist_list *list,
if ((result = sqlite3_step(stmt)) == SQLITE_ROW) if ((result = sqlite3_step(stmt)) == SQLITE_ROW)
list->id = sqlite3_column_int(stmt, 0); list->id = sqlite3_column_int(stmt, 0);
else else
klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n",
result); sqlite3_errmsg(ctx->db), result);
sqlite3_reset(stmt); sqlite3_reset(stmt);
if (list->id > -1) { if (list->id > -1) {
stmt = ctx->stmts[ADD_USER_LIST]; stmt = ctx->stmts[ADD_USER_LIST];
sqlite3_bind_int(stmt, 1, list->id); 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) if (sqlite3_step(stmt) == SQLITE_DONE)
sqlite3_reset(stmt); sqlite3_reset(stmt);
else else
klist_print(ctx, KLIST_LOG_ERROR, "failed to save user - list relation in join table: %s\n", klist_print(ctx, KLIST_LOG_ERROR,
sqlite3_errmsg(ctx->db)); "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) if (sqlite3_step(stmt) == SQLITE_ROW)
task = klist_task_init_from_sql(stmt); task = klist_task_init_from_sql(stmt);
else else
klist_print(ctx, KLIST_LOG_WARNING, "no tasks found for list %d, name '%s': %s\n", list_id, klist_print(ctx, KLIST_LOG_WARNING,
name, sqlite3_errmsg(ctx->db)); "no tasks found for list %d, name '%s': %s\n", list_id, name,
sqlite3_errmsg(ctx->db));
sqlite3_reset(stmt); sqlite3_reset(stmt);
return task; return task;
} }
@ -340,8 +345,8 @@ void klist_task_save(const klist *ctx, klist_task *task) {
if ((result = sqlite3_step(stmt)) == SQLITE_ROW) { if ((result = sqlite3_step(stmt)) == SQLITE_ROW) {
task->id = sqlite3_column_int(stmt, 0); task->id = sqlite3_column_int(stmt, 0);
} else } else
klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n",
result); sqlite3_errmsg(ctx->db), result);
sqlite3_reset(stmt); sqlite3_reset(stmt);
} }
void klist_task_delete(const klist *ctx, const klist_task *task) { 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) if (sqlite3_step(stmt) == SQLITE_DONE)
sqlite3_reset(stmt); sqlite3_reset(stmt);
else 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) { void klist_task_deinit(klist_task *task) {

View file

@ -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 " return "select users.*, user_logins.local_id from users inner join "
"user_logins on user_logins.user_id = users.id where users.id = ?1"; "user_logins on user_logins.user_id = users.id where users.id = ?1";
case GET_USER_BY_LOCAL: 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"; "= users.id where user_logins.local_id = ?1";
case GET_USERS: case GET_USERS:
return "select * from users"; return "select * from users";

View file

@ -97,23 +97,30 @@ void klist_task_context_deinit(klist_task_context *ctx) {
*/ */
void klist_sql_prepare(klist *ctx, char *db) { 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) { 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; return;
} }
char *errmsg = NULL; char *errmsg = NULL;
sqlite3_exec(ctx->db, klist_sql_get(INIT), NULL, NULL, &errmsg); sqlite3_exec(ctx->db, klist_sql_get(INIT), NULL, NULL, &errmsg);
if (errmsg) { if (errmsg) {
klist_print(ctx, KLIST_LOG_ERROR, "Database initialization failed (%s), expect issues.\n", klist_print(ctx, KLIST_LOG_ERROR,
sqlite3_errmsg(ctx->db)); "Database initialization failed (%s), expect issues.\n",
sqlite3_errmsg(ctx->db));
sqlite3_free(errmsg); sqlite3_free(errmsg);
} }
int i = 0; int i = 0;
for (; i < _KLIST_SQL_COUNT; i++) for (; i < _KLIST_SQL_COUNT; i++)
if (sqlite3_prepare(ctx->db, klist_sql_get(i), -1, &ctx->stmts[i], NULL) != if (sqlite3_prepare(ctx->db, klist_sql_get(i), -1, &ctx->stmts[i], NULL) !=
SQLITE_OK) 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) {} void klist_sql_seed(klist *ctx) {}
@ -143,13 +150,22 @@ void klist_assure_task(klist *, char *);
* printing methods * 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) { if (ctx->log_level >= log_level) {
switch (log_level) { switch (log_level) {
case KLIST_LOG_DEBUG: fprintf(ctx->log_target, "[\x1B[34mDBG\x1B[0m] "); break; case KLIST_LOG_DEBUG:
case KLIST_LOG_INFO: fprintf(ctx->log_target, "[\x1B[36mINF\x1B[0m] "); break; fprintf(ctx->log_target, "[\x1B[34mDBG\x1B[0m] ");
case KLIST_LOG_WARNING: fprintf(ctx->log_target, "[\x1B[33mWRN\x1B[0m] "); break; break;
case KLIST_LOG_ERROR: fprintf(ctx->log_target, "[\x1B[31mERR\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_list args;
va_start(args, format); va_start(args, format);

View file

@ -1,403 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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 <action>\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 <preset>\tdefine as preset or use existing one with name "
"<preset>\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);
}
}