#include <pakfire/archive.h>
#include <pakfire/build.h>
+#include <pakfire/log_file.h>
#include <pakfire/package.h>
#include <pakfire/pakfire.h>
#include <pakfire/path.h>
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;
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 },
args->flags &= ~BUILD_ENABLE_TESTS;
break;
+ case OPT_LOG_FILE:
+ args->log_path = arg;
+ break;
+
case OPT_NON_INTERACTIVE:
args->flags &= ~BUILD_INTERACTIVE;
break;
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,
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)
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)
}
ERROR:
+ if (local_args.log_file)
+ pakfire_log_file_unref(local_args.log_file);
if (build)
pakfire_build_unref(build);
// Flags
int flags;
+ // Internal Flags
+ enum pakfire_log_file_internal_flags {
+ PAKFIRE_LOG_FILE_UNLINK = (1 << 0),
+ } internal_flags;
+
// Path
char path[PATH_MAX];
// 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;
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