From 0bd5bb65f65ce7f1d358ec676acef67447af6288 Mon Sep 17 00:00:00 2001 From: yukkop Date: Thu, 6 Mar 2025 16:07:53 +0100 Subject: [PATCH] refector(pg-neo-migration): stir some shit around trust me it's fine --- package/postgres/pg-neo-migration/hectic-chan | Bin 20136 -> 50592 bytes package/postgres/pg-neo-migration/pup | 1 + .../postgres/pg-neo-migration/src/logger.c | 119 +++++++++++++ .../postgres/pg-neo-migration/src/macros.c | 9 + .../postgres/pg-neo-migration/src/macros.h | 45 +++++ package/postgres/pg-neo-migration/src/main.c | 157 +++++++++++++++++- package/postgres/pg-neo-migration/src/type.c | 8 - 7 files changed, 323 insertions(+), 16 deletions(-) create mode 100644 package/postgres/pg-neo-migration/pup create mode 100644 package/postgres/pg-neo-migration/src/logger.c create mode 100644 package/postgres/pg-neo-migration/src/macros.c create mode 100644 package/postgres/pg-neo-migration/src/macros.h delete mode 100644 package/postgres/pg-neo-migration/src/type.c diff --git a/package/postgres/pg-neo-migration/hectic-chan b/package/postgres/pg-neo-migration/hectic-chan index deef93d0e6c69fad283547dda1aee3f2641d7ca4..bfa0aafb33e3815e2ed81b58805799a9f2d838ce 100755 GIT binary patch literal 50592 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 Pik*RhAqh +#include +#include +#include +#include "macros.h" + +typedef enum { + LOG_LEVEL_DEBUG, + LOG_LEVEL_LOG, + LOG_LEVEL_INFO, + LOG_LEVEL_NOTICE, + LOG_LEVEL_WARN, + LOG_LEVEL_EXCEPTION +} LogLevel; + +const char* log_level_to_string(LogLevel level) { + switch (level) { + case LOG_LEVEL_DEBUG: return "DEBUG"; + case LOG_LEVEL_LOG: return "LOG"; + case LOG_LEVEL_INFO: return "INFO"; + case LOG_LEVEL_NOTICE: return "NOTICE"; + case LOG_LEVEL_WARN: return "WARN"; + case LOG_LEVEL_EXCEPTION: return "EXCEPTION"; + default: return "UNKNOWN"; + } +} + +LogLevel log_level_from_string(const char *level_str) { + if (!level_str) return LOG_LEVEL_INFO; + if (strcmp(level_str, "DEBUG") == 0) + return LOG_LEVEL_DEBUG; + else if (strcmp(level_str, "LOG") == 0) + return LOG_LEVEL_LOG; + else if (strcmp(level_str, "INFO") == 0) + return LOG_LEVEL_INFO; + else if (strcmp(level_str, "NOTICE") == 0) + return LOG_LEVEL_NOTICE; + else if (strcmp(level_str, "WARN") == 0) + return LOG_LEVEL_WARN; + else if (strcmp(level_str, "EXCEPTION") == 0) + return LOG_LEVEL_EXCEPTION; + else + return LOG_LEVEL_INFO; +} + +LogLevel current_log_level = LOG_LEVEL_INFO; + +void init_logger(void) { + current_log_level = log_level_from_string(getenv("LOG_LEVEL")); +} + +void log_message(LogLevel level, int line, const char *format, ...) { + if (level < current_log_level) { + return; + } + + time_t now = time(NULL); + struct tm tm_info; + localtime_r(&now, &tm_info); + char timeStr[20]; + strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &tm_info); + + fprintf(stderr, "%s %d %s: ", timeStr, line, log_level_to_string(level)); + + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + + fprintf(stderr, "\n"); +} + +// DEBUG level +#define raise_debug_1(fmt) \ + log_message(LOG_LEVEL_DEBUG, __LINE__, fmt) +#define raise_debug_2(fmt, ...) \ + log_message(LOG_LEVEL_DEBUG, __LINE__, fmt, __VA_ARGS__) +#define raise_debug(...) \ + PP_CAT(raise_debug_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) + +// LOG level +#define raise_log_1(fmt) \ + log_message(LOG_LEVEL_LOG, __LINE__, fmt) +#define raise_log_2(fmt, ...) \ + log_message(LOG_LEVEL_LOG, __LINE__, fmt, __VA_ARGS__) +#define raise_log(...) \ + PP_CAT(raise_log_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) + +// INFO level +#define raise_info_1(fmt) \ + log_message(LOG_LEVEL_INFO, __LINE__, fmt) +#define raise_info_2(fmt, ...) \ + log_message(LOG_LEVEL_INFO, __LINE__, fmt, __VA_ARGS__) +#define raise_info(...) \ + PP_CAT(raise_info_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) + +// NOTICE level +#define raise_notice_1(fmt) \ + log_message(LOG_LEVEL_NOTICE, __LINE__, fmt) +#define raise_notice_2(fmt, ...) \ + log_message(LOG_LEVEL_NOTICE, __LINE__, fmt, __VA_ARGS__) +#define raise_notice(...) \ + PP_CAT(raise_notice_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) + +// WARN level +#define raise_warn_1(fmt) \ + log_message(LOG_LEVEL_WARN, __LINE__, fmt) +#define raise_warn_2(fmt, ...) \ + log_message(LOG_LEVEL_WARN, __LINE__, fmt, __VA_ARGS__) +#define raise_warn(...) \ + PP_CAT(raise_warn_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) + +// EXCEPTION level +#define raise_exception_1(fmt) \ + log_message(LOG_LEVEL_EXCEPTION, __LINE__, fmt) +#define raise_exception_2(fmt, ...) \ + log_message(LOG_LEVEL_EXCEPTION, __LINE__, fmt, __VA_ARGS__) +#define raise_exception(...) \ + PP_CAT(raise_exception_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) diff --git a/package/postgres/pg-neo-migration/src/macros.c b/package/postgres/pg-neo-migration/src/macros.c new file mode 100644 index 0000000..1b61d85 --- /dev/null +++ b/package/postgres/pg-neo-migration/src/macros.c @@ -0,0 +1,9 @@ +#include "macros.h" + +// Static color mode variable +static ColorMode color_mode = COLOR_MODE_AUTO; + +// Function to set color mode +void set_output_color_mode(ColorMode mode) { + color_mode = mode; +} diff --git a/package/postgres/pg-neo-migration/src/macros.h b/package/postgres/pg-neo-migration/src/macros.h new file mode 100644 index 0000000..b1649be --- /dev/null +++ b/package/postgres/pg-neo-migration/src/macros.h @@ -0,0 +1,45 @@ +#ifndef EPRINTF_H +#define EPRINTF_H + +#include +#include + +// Color mode enumeration +typedef enum { + COLOR_MODE_AUTO, + COLOR_MODE_FORCE, + COLOR_MODE_DISABLE +} ColorMode; + +// Function to set the color mode +void set_output_color_mode(ColorMode mode); + +// Macros for detecting terminal and color usage +#define IS_TERMINAL() (isatty(fileno(stderr))) +#define USE_COLOR() ((color_mode == COLOR_MODE_FORCE) || (color_mode == COLOR_MODE_AUTO && IS_TERMINAL())) + +// Define color macros based on output type +#define ERROR_PREFIX (IS_TERMINAL() ? "\033[1;31mError: " : "Error: ") +#define ERROR_SUFFIX (IS_TERMINAL() ? "\033[0m\n" : "\n") + +// Helper macros for argument counting +// NOTE(yukkop): this ugly macroses for avoid all posible warnings +#define PP_CAT(a, b) PP_CAT_I(a, b) +#define PP_CAT_I(a, b) a##b + +#define PP_NARG(...) PP_NARG_(__VA_ARGS__, PP_RSEQ_N()) +#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__) +#define PP_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N +#define PP_RSEQ_N() 9,8,7,6,5,4,3,2,1,0 + +// eprintf handling 1 or more arguments +#define eprintf_1(fmt) \ + fprintf(stderr, "%s" fmt "%s", ERROR_PREFIX, ERROR_SUFFIX) + +#define eprintf_2(fmt, ...) \ + fprintf(stderr, "%s" fmt "%s", ERROR_PREFIX, __VA_ARGS__, ERROR_SUFFIX) + +#define eprintf(...) \ + PP_CAT(eprintf_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) + +#endif // EPRINTF_H diff --git a/package/postgres/pg-neo-migration/src/main.c b/package/postgres/pg-neo-migration/src/main.c index 6883f23..ebc96ce 100644 --- a/package/postgres/pg-neo-migration/src/main.c +++ b/package/postgres/pg-neo-migration/src/main.c @@ -1,27 +1,168 @@ #include #include -#include "type.c" - -LogLevel currentLogLevel = LOG_LEVEL_DEBUG; +#include "logger.c" +#include "macros.h" +#include +#include +#include // TODO: check on the specific psql version int check_psql_installed(void) { + raise_log("checking psql installed..."); int returned = system("psql --version > /dev/null 2>&1"); if (returned != 0) { - fprintf(stderr, "Error: psql is not installed or not in PATH.\n"); + raise_log("psql is not installed..."); + eprintf("psql is not installed or not in PATH."); return 1; } + raise_log("psql is installed..."); return 0; } -void help_message() { - fprintf(stdout, "Usage: TODO"); +/* Generate a migration name by choosing a random adjective and noun */ +void generate_migration_name(char *buffer, size_t size) { + const char *adjectives[] = {"quick", "lazy", "sleepy", "noisy", "hungry"}; + const char *nouns[] = {"fox", "dog", "cat", "mouse", "bear"}; + int num_adjectives = sizeof(adjectives) / sizeof(adjectives[0]); + int num_nouns = sizeof(nouns) / sizeof(nouns[0]); + int adj_index = rand() % num_adjectives; + int noun_index = rand() % num_nouns; + snprintf(buffer, size, "%s_%s", adjectives[adj_index], nouns[noun_index]); +} + +/* Record that a migration has been applied + * by inserting its filename into the database */ +int record_migration(const char* db_url, const char* file_name) { + char command[2048]; + snprintf(command, sizeof(command), + "psql '%s' -c \"INSERT INTO hectic.migration (name) VALUES ('%s');\"", + db_url, file_name); + int returned = system(command); + return returned; +} + +void create_migration_inner(const char* migration_path, const char* type) { + if (strcmp(type, "up") || strcmp(type, "down")) { + raise_exception("migration type can only be up or down"); + exit(1); + } + + char path[1024]; + snprintf(path, sizeof(path), "%s/%s", migration_path, type); + + /* create directory for current migration */ + if (mkdir(path, 0755) != 0 && errno != EEXIST) { + eprintf("Error creating %s", path); + exit(1); + } + + char filename[1024]; + snprintf(filename, sizeof(filename), "%s/00-entry-point.sql", path); + + FILE *fp = fopen(filename, "w"); + if (!fp) { + eprintf("Error creating %s", filename); + exit(1); + } + fprintf(fp, "-- Write your migration SQL here\n"); + fclose(fp); + printf("Created migration: %s\n", filename); + +} + +/* Create a migration in the given directory with the provided name. + * The migration name is formed as "_.sql". */ +void create_migration(const char* migration_dir, const char* name) { + /* Create the directory if it doesn't exist */ + if (mkdir(migration_dir, 0755) != 0 && errno != EEXIST) { + eprintf("Error creating migration directory"); + exit(1); + } + + /* create directory for current migration */ + time_t now = time(NULL); + char path[1024]; + snprintf(path, sizeof(path), "%s/%ld-%s", migration_dir, now, name); + + if (mkdir(path, 0755) != 0 && errno != EEXIST) { + eprintf("Error creating %s", path); + exit(1); + } + + create_migration_inner(path, "up"); + create_migration_inner(path, "down"); +} + +void help_message(char name[]) { + fprintf(stdout, "Usage %s: TODO\n", name); } int main(int argc, char *argv[]) { - if (!check_psql_installed()) { exit(1); } + srand(time(NULL)); + init_logger(); + + raise_log("init"); + + if (check_psql_installed()) { exit(1); } if (argc < 2) { - help_message(); + help_message(argv[0]); + exit(0); } + + int subcommand_index = 0; + char *migration_dir; + char *db_url; + char *migration_name; + + /* Process global options until a known subcommand is encountered */ + int i = 1; + for (; i < argc; i++) { + if (strcmp(argv[i], "create") == 0 || + strcmp(argv[i], "migrate") == 0 || + strcmp(argv[i], "fetch") == 0) { + subcommand_index = i; + break; + } + if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--migration-dir") == 0) { + if (i+1 < argc) { + migration_dir = argv[i+1]; + i++; + } + } + } + + if (subcommand_index == 0) { + eprintf("No subcommand provided.\n"); + help_message(argv[0]); + exit(1); + } + + char *subcommand = argv[subcommand_index]; + + if (strcmp(subcommand, "create") == 0) { + for (i = subcommand_index+1; i < argc; i++) { + if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--name") == 0) { + if (i+1 < argc) { + migration_name = argv[i+1]; + i++; + } + } + } + char generated_name[128]; + if (!migration_name) { + generate_migration_name(generated_name, sizeof(generated_name)); + migration_name = generated_name; + } + create_migration(migration_dir, migration_name); + return 0; + } + + if (!db_url) { + eprintf("Database URL is required for migrate subcommand.\n"); + help_message(argv[0]); + exit(1); + } + + } diff --git a/package/postgres/pg-neo-migration/src/type.c b/package/postgres/pg-neo-migration/src/type.c deleted file mode 100644 index 722deb0..0000000 --- a/package/postgres/pg-neo-migration/src/type.c +++ /dev/null @@ -1,8 +0,0 @@ -typedef enum { - LOG_LEVEL_DEBUG, - LOG_LEVEL_LOG, - LOG_LEVEL_INFO, - LOG_LEVEL_NOTICE, - LOG_LEVEL_WARN, - LOG_LEVEL_EXCEPTION -} LogLevel;