From: Michael Tremer Date: Fri, 14 Feb 2025 15:12:16 +0000 (+0000) Subject: build: Add CLI switch to write the build log to file X-Git-Tag: 0.9.30~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=18ac96e3e7d956894d4897501033f0cdceb2f37d;p=pakfire.git build: Add CLI switch to write the build log to file Signed-off-by: Michael Tremer --- diff --git a/src/cli/lib/build.c b/src/cli/lib/build.c index 405cd1ef..75b0febc 100644 --- a/src/cli/lib/build.c +++ b/src/cli/lib/build.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -47,6 +48,10 @@ struct cli_local_args { BUILD_ENABLE_TESTS = (1 << 3), } flags; + // Log file + struct pakfire_log_file* log_file; + const char* log_path; + // Makefiles char* makefiles[MAX_MAKEFILES]; unsigned int num_makefiles; @@ -56,14 +61,16 @@ enum { OPT_DISABLE_CCACHE = 1, OPT_DISABLE_SNAPSHOT = 2, OPT_DISABLE_TESTS = 3, - OPT_NON_INTERACTIVE = 4, - OPT_TARGET = 5, + OPT_LOG_FILE = 4, + OPT_NON_INTERACTIVE = 5, + OPT_TARGET = 6, }; static struct argp_option options[] = { { "disable-ccache", OPT_DISABLE_CCACHE, NULL, 0, "Disable the ccache", 0 }, { "disable-snapshot", OPT_DISABLE_SNAPSHOT, NULL, 0, "Do not use the snapshot", 0 }, { "disable-tests", OPT_DISABLE_TESTS, NULL, 0, "Do not run tests", 0 }, + { "log-file", OPT_LOG_FILE, "PATH", 0, "Writes the log to a file", 0 }, { "non-interactive", OPT_NON_INTERACTIVE, NULL, 0, "Run the build non-interactively", 0 }, { "target", OPT_TARGET, "TARGET", 0, "Output all packages into this directory", 0 }, { NULL }, @@ -85,6 +92,10 @@ static error_t parse(int key, char* arg, struct argp_state* state, void* data) { args->flags &= ~BUILD_ENABLE_TESTS; break; + case OPT_LOG_FILE: + args->log_path = arg; + break; + case OPT_NON_INTERACTIVE: args->flags &= ~BUILD_INTERACTIVE; break; @@ -113,34 +124,43 @@ static void log_callback(void* data, int priority, const char* file, int line, static void log_callback(void* data, int priority, const char* file, int line, const char* function, const char* format, va_list args) { - va_list args_copy; + const struct cli_local_args* local_args = data; + char* buffer = NULL; + ssize_t length; + int r; + + // Format the line + length = vasprintf(&buffer, format, args); + if (length < 0) + return; - // Make a copy of args because we can only use them once... - va_copy(args_copy, args); switch (priority) { // Print messages to standard output case LOG_INFO: - vfprintf(stdout, format, args_copy); + fprintf(stdout, "%s", buffer); break; // Highlight any warnings case LOG_WARNING: fputs(color_yellow(), stderr); - vfprintf(stderr, format, args_copy); + fprintf(stderr, "%s", buffer); fputs(color_reset(), stderr); break; // Highlight any error messages case LOG_ERR: fputs(color_highlight(), stderr); - vfprintf(stderr, format, args_copy); + fprintf(stderr, "%s", buffer); fputs(color_reset(), stderr); break; } - va_end(args_copy); - // Send everything to the default logger, too - pakfire_log_syslog(NULL, priority, file, line, function, format, args); + // Write to the log file + if (local_args->log_file) + pakfire_log_file_write(local_args->log_file, buffer, length); + + if (buffer) + free(buffer); } static int result_callback(struct pakfire_ctx* ctx, struct pakfire* pakfire, @@ -217,7 +237,7 @@ int cli_build(void* data, int argc, char* argv[]) { goto ERROR; // Replace the logger - pakfire_ctx_set_log_callback(global_args->ctx, log_callback, NULL); + pakfire_ctx_set_log_callback(global_args->ctx, log_callback, &local_args); // Use the snapshot? if (local_args.flags & BUILD_ENABLE_SNAPSHOT) @@ -235,6 +255,14 @@ int cli_build(void* data, int argc, char* argv[]) { if (!(local_args.flags & BUILD_ENABLE_TESTS)) flags |= PAKFIRE_BUILD_DISABLE_TESTS; + // Create the log file + if (local_args.log_path) { + r = pakfire_log_file_create(&local_args.log_file, + global_args->ctx, local_args.log_path, NULL, 0); + if (r < 0) + goto ERROR; + } + // Setup the build environment r = cli_setup_build(&build, global_args, flags); if (r < 0) @@ -251,6 +279,8 @@ int cli_build(void* data, int argc, char* argv[]) { } ERROR: + if (local_args.log_file) + pakfire_log_file_unref(local_args.log_file); if (build) pakfire_build_unref(build); diff --git a/src/pakfire/job.c b/src/pakfire/job.c index 8468c55d..a6374ae5 100644 --- a/src/pakfire/job.c +++ b/src/pakfire/job.c @@ -659,7 +659,7 @@ static int pakfire_job_child(struct pakfire_job* job) { pakfire_ctx_set_log_callback(ctx, pakfire_job_log, job); // Open a new log file - r = pakfire_log_file_create(&job->log.file, ctx, job->id, PAKFIRE_LOG_FILE_COMPRESS); + r = pakfire_log_file_create(&job->log.file, ctx, NULL, job->id, PAKFIRE_LOG_FILE_COMPRESS); if (r < 0) { ERROR(ctx, "Could not open log file: %s\n", strerror(-r)); goto ERROR; diff --git a/src/pakfire/log_file.c b/src/pakfire/log_file.c index 7b54c435..dab4a03e 100644 --- a/src/pakfire/log_file.c +++ b/src/pakfire/log_file.c @@ -37,6 +37,11 @@ struct pakfire_log_file { // Flags int flags; + // Internal Flags + enum pakfire_log_file_internal_flags { + PAKFIRE_LOG_FILE_UNLINK = (1 << 0), + } internal_flags; + // Path char path[PATH_MAX]; @@ -48,16 +53,19 @@ static void pakfire_log_file_free(struct pakfire_log_file* self) { // Close the log file pakfire_log_file_close(self); - // Free all held resources - if (*self->path) - unlink(self->path); + // Unlink the file + if (self->internal_flags & PAKFIRE_LOG_FILE_UNLINK) { + if (*self->path) + unlink(self->path); + } + if (self->ctx) pakfire_ctx_unref(self->ctx); free(self); } int pakfire_log_file_create(struct pakfire_log_file** file, struct pakfire_ctx* ctx, - const char* filename, int flags) { + const char* path, const char* filename, int flags) { struct pakfire_log_file* self = NULL; int r; @@ -80,16 +88,35 @@ int pakfire_log_file_create(struct pakfire_log_file** file, struct pakfire_ctx* if (r < 0) goto ERROR; - // Make some path - r = pakfire_string_set(self->path, PAKFIRE_TMP_DIR "/pakfire-log.XXXXXX"); - if (r < 0) - goto ERROR; + // Store the path + if (path) { + r = pakfire_string_set(self->path, path); + if (r < 0) + goto ERROR; - // Create a new temporary file - self->f = pakfire_mktemp(self->path, 0600); - if (!self->f) { - r = -errno; - goto ERROR; + // Open the file + self->f = fopen(self->path, "w"); + if (!self->f) { + ERROR(self->ctx, "Failed to open %s for writing: %m\n", self->path); + goto ERROR; + } + + // If no path has been given, we create a new temporary file + } else { + // Make some path + r = pakfire_string_set(self->path, PAKFIRE_TMP_DIR "/pakfire-log.XXXXXX"); + if (r < 0) + goto ERROR; + + // Create a new temporary file + self->f = pakfire_mktemp(self->path, 0600); + if (!self->f) { + r = -errno; + goto ERROR; + } + + // Remove the temporary file afterwards + self->internal_flags |= PAKFIRE_LOG_FILE_UNLINK; } // If we want to write the log file compressed, we replace the file handle diff --git a/src/pakfire/log_file.h b/src/pakfire/log_file.h index 2f60aa34..584cfcd3 100644 --- a/src/pakfire/log_file.h +++ b/src/pakfire/log_file.h @@ -34,7 +34,7 @@ enum pakfire_log_file_flags { }; int pakfire_log_file_create(struct pakfire_log_file** file, - struct pakfire_ctx* ctx, const char* filename, int flags); + struct pakfire_ctx* ctx, const char* path, const char* filename, int flags); struct pakfire_log_file* pakfire_log_file_ref(struct pakfire_log_file* self); struct pakfire_log_file* pakfire_log_file_unref(struct pakfire_log_file* self); diff --git a/tests/libpakfire/log_file.c b/tests/libpakfire/log_file.c index aeb37a5c..845effed 100644 --- a/tests/libpakfire/log_file.c +++ b/tests/libpakfire/log_file.c @@ -31,7 +31,7 @@ static int __test_simple(const struct test* t, int flags) { int r = EXIT_FAILURE; // Create a new log file - ASSERT_SUCCESS(pakfire_log_file_create(&file, t->ctx, "test.log", flags)); + ASSERT_SUCCESS(pakfire_log_file_create(&file, t->ctx, NULL, "test.log", flags)); // Store a copy of the path ASSERT_SUCCESS(pakfire_string_set(path, pakfire_log_file_path(file)));