From 0d5da72b13d79f4e7de969a5e07b7d96bc26ca3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Rivera?= Date: Mon, 17 Aug 2026 17:42:48 +0200 Subject: [PATCH] feat: show warning if git operation too slow --- CONTRIBUTING.md | 4 +++- src/utils.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++-- src/utils.h | 3 +++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e1dcab..416e648 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ This project aims to remain minimal, terminal-focused, and easy to extend. Contr Please use the standardized debugging and error-handling functions defined in [/src/utils.c](./src/utils.c): -* `debug(...)` +* `debug("message", ...)` Used for formatted debugging output (printf-style formatting). * `altDebug(...)` @@ -21,6 +21,8 @@ Please use the standardized debugging and error-handling functions defined in [/ * `"user"`: errors caused by user input or configuration * `"program"`: internal or unexpected program errors +* `warn(condition, "message", ...)` + Used for formatted warning (printf-style formatting). --- diff --git a/src/utils.c b/src/utils.c index fe9fe56..c4884ae 100644 --- a/src/utils.c +++ b/src/utils.c @@ -71,6 +71,29 @@ void _error(const int shouldDebug, const int condition, const char *type, const exit(1); } } +void _warn(const int condition, const char *file, const int line, const char *function, + const char *message, ...) { // use for warnings that should always be shown + if (condition) { + fflush(stdout); + fflush(stderr); + + va_list args; + va_start(args, message); + + int h, m, s; + getCurrentTime(&h, &m, &s); + + fprintf(stdout, + "\e[0;33m[WARNING -- %d:%d:%d] From file %s line %d function %s:\e[0m\n", + h, m, s, file, line, function); + + vfprintf(stdout, message, args); + + fprintf(stdout, "\e[0m\n"); + + va_end(args); + } +} static void copyDir(const char *source, const char *destination, const char **rsyncArgs, const int rsyncArgsNumber, const int shouldDebug) { debug("Backuping... source: %s and destination: %s", source, destination); @@ -113,6 +136,21 @@ static void ensureDir(const char *path, const int shouldDebug) { } } +static void slowGitWarning(struct timespec start, int *wasShown) { + if (!*wasShown) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + double elapsed = (double)(now.tv_sec - start.tv_sec) + + (double)(now.tv_nsec - start.tv_nsec) / 1e9; + + warn(elapsed > 0.3, "Git operations are taking too much time. You drive might be slow. Please do not stop the program."); + if (elapsed > 0.3) { + *wasShown = 1; + } + } +} + void ensureGitDirectory(const char *path, const char *vault, const char *signatureName, const char *signatureEmail, const int shouldDebug) { git_repository *repo = NULL; char *fullPath = malloc(PATH_MAX); @@ -151,6 +189,10 @@ void ensureGitDirectory(const char *path, const char *vault, const char *signatu } void gitBackupUpdate(const char *path, const char *vault, const char *signatureName, const char *signatureEmail, const char *commitMsg, const int shouldDebug) { + // on slow drive or WebDav mounted drive this git operations are pretty slow. We'll just show a warning to avoid the user closing the program. + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); + git_repository *repo = NULL; git_index *index = NULL; git_tree *tree = NULL; @@ -162,6 +204,8 @@ void gitBackupUpdate(const char *path, const char *vault, const char *signatureN git_oid tree_id; git_oid commit_id; + int slowGitWarningAlreadyShown = 0; + char *fullPath = malloc(PATH_MAX); error(fullPath == NULL, "program", "Failed to allocate path"); @@ -172,18 +216,25 @@ void gitBackupUpdate(const char *path, const char *vault, const char *signatureN int return_code = git_repository_open(&repo, fullPath); error(return_code, "program", "Failed to open Git repository\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); + /* Get the index */ return_code = git_repository_index(&index, repo); error(return_code, "program", "Failed to get Git index\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); + /* git add . */ return_code = git_index_add_all(index, NULL, 0, NULL, NULL); error(return_code, "program", "Failed to add files\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); + return_code = git_index_write(index); error(return_code, "program", "Failed to write index\n%s", git_error_last()->message); - + slowGitWarning(start, &slowGitWarningAlreadyShown); + /* * Check whether there are changes to commit. * @@ -199,16 +250,19 @@ void gitBackupUpdate(const char *path, const char *vault, const char *signatureN return_code = git_reference_name_to_id(&head_oid, repo, "HEAD"); error(return_code, "program", "Failed to get HEAD\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); return_code = git_commit_lookup(&head_commit, repo, &head_oid); error(return_code, "program", "Failed to lookup HEAD commit\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); return_code = git_commit_tree(&head_tree, head_commit); error(return_code, "program", "Failed to get HEAD tree\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); return_code = git_diff_tree_to_index(&diff, repo, head_tree, index, NULL); - error(return_code, "program", "Failed to create diff\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); has_changes = git_diff_num_deltas(diff) > 0; } @@ -222,13 +276,16 @@ void gitBackupUpdate(const char *path, const char *vault, const char *signatureN /* index → tree */ return_code = git_index_write_tree(&tree_id, index); error(return_code, "program", "Failed to write tree\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); return_code = git_tree_lookup(&tree, repo, &tree_id); error(return_code, "program", "Failed to lookup tree\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); /* Author/committer */ return_code = git_signature_now(&signature, signatureName, signatureEmail); error(return_code, "program", "Failed to create signature\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); /* Create commit */ if (git_repository_head_unborn(repo)) { @@ -237,6 +294,7 @@ void gitBackupUpdate(const char *path, const char *vault, const char *signatureN return_code = git_commit_create_v(&commit_id, repo, "HEAD", signature, signature, NULL, commitMsg, tree, 1, head_commit); } error(return_code, "program", "Failed to create commit\n%s", git_error_last()->message); + slowGitWarning(start, &slowGitWarningAlreadyShown); debug("Created commit %s in %s", commitMsg, fullPath); diff --git a/src/utils.h b/src/utils.h index c064e52..e8ed0f1 100644 --- a/src/utils.h +++ b/src/utils.h @@ -31,6 +31,7 @@ #define debug(message, ...) _debug(shouldDebug, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__) #define altDebug(message, ...) _altDebug(shouldDebug, message, ##__VA_ARGS__) #define error(condition, type, message, ...) _error(shouldDebug, condition, type, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__) +#define warn(condition, message, ...) _warn(condition, __FILE__, __LINE__, __func__, message, ##__VA_ARGS__) // you must edit this two values if you want to add suport for an editor extern const char *supportedEditor[]; // array of supported editors extern const int numEditors; // number of supported editors @@ -53,6 +54,8 @@ void _debug(const int d, const char *file, const int line, const char *function, void _altDebug(const int d, const char *message, ...); // formated error. void _error(const int shouldDebug, const int condition, const char *type, const char *file, const int line, const char *function, const char *message, ...); +// formated warn +void _warn(const int condition, const char *file, const int line, const char *function, const char *message, ...); // Returns 1 if the string is in the array. // Returns 0 if the string is not in the array. // If you want to only check the first n elements of the array, pass n as len.