From 792ac4ec66dd098109a88065420ef95c1a78624f Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sat, 27 Apr 2019 04:22:56 +0200 Subject: make: support posts autoloading --- src/blogc-make/ctx.c | 108 ++++++++++++++++++++++++++++++++++++++++++++-- src/blogc-make/ctx.h | 3 ++ src/blogc-make/rules.c | 48 ++++++++++++--------- src/blogc-make/settings.c | 1 + 4 files changed, 136 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/blogc-make/ctx.c b/src/blogc-make/ctx.c index 423b334..d7a503d 100644 --- a/src/blogc-make/ctx.c +++ b/src/blogc-make/ctx.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -267,7 +268,11 @@ bm_ctx_new(bm_ctx_t *base, const char *settings_file, const char *argv0, } rv->posts_fctx = NULL; - if (settings->posts != NULL) { + rv->posts_deleted = false; + if (bc_str_to_bool(bc_trie_lookup(settings->settings, "posts_autoload"))) { + bm_ctx_autoload_posts(rv); + } + else if (settings->posts != NULL) { for (size_t i = 0; settings->posts[i] != NULL; i++) { char *f = bm_generate_filename(content_dir, post_prefix, settings->posts[i], source_ext); @@ -306,7 +311,7 @@ bm_ctx_reload(bm_ctx_t **ctx) if (*ctx == NULL || (*ctx)->settings_fctx == NULL) return false; - if (bm_filectx_changed((*ctx)->settings_fctx, NULL, NULL)) { + if ((*ctx)->posts_deleted || bm_filectx_changed((*ctx)->settings_fctx, NULL, NULL)) { // reload everything! we could just reload settings_fctx, as this // would force rebuilding everything, but we need to know new/deleted // files @@ -328,8 +333,13 @@ bm_ctx_reload(bm_ctx_t **ctx) bm_filectx_reload((*ctx)->atom_template_fctx); bm_filectx_reload((*ctx)->listing_entry_fctx); - for (bc_slist_t *tmp = (*ctx)->posts_fctx; tmp != NULL; tmp = tmp->next) - bm_filectx_reload((bm_filectx_t*) tmp->data); + if (bc_str_to_bool(bm_ctx_settings_lookup(*ctx, "posts_autoload"))) { + bm_ctx_autoload_posts(*ctx); + } + else { + for (bc_slist_t *tmp = (*ctx)->posts_fctx; tmp != NULL; tmp = tmp->next) + bm_filectx_reload((bm_filectx_t*) tmp->data); + } for (bc_slist_t *tmp = (*ctx)->pages_fctx; tmp != NULL; tmp = tmp->next) bm_filectx_reload((bm_filectx_t*) tmp->data); @@ -341,6 +351,96 @@ bm_ctx_reload(bm_ctx_t **ctx) } +void +bm_ctx_autoload_posts(bm_ctx_t *ctx) +{ + if (ctx == NULL) + return; + + const char *content_dir = bm_ctx_settings_lookup(ctx, "content_dir"); + const char *post_prefix = bm_ctx_settings_lookup(ctx, "post_prefix"); + const char *source_ext = bm_ctx_settings_lookup(ctx, "source_ext"); + + char *posts_dir = bm_generate_filename(content_dir, post_prefix, NULL, NULL); + char *abs_posts_dir = bc_strdup_printf("%s/%s", ctx->root_dir, posts_dir); + DIR *dir = opendir(abs_posts_dir); + if (dir == NULL) { + fprintf(stderr, + "blogc-make: warning: failed to open directory for posts autoload " + "(%s): %s\n", abs_posts_dir, strerror(errno)); + free(posts_dir); + free(abs_posts_dir); + return; + } + free(abs_posts_dir); + + // trick 0: avoid additional loops if we are not reloading + bool reloading = ctx->posts_fctx != NULL; + + // trick 1: set all the post file contexts as unreadable, so we can detect + // which ones were deleted. + for (bc_slist_t *tmp = ctx->posts_fctx; tmp != NULL; tmp = tmp->next) { + bm_filectx_t *fc = tmp->data; + if (fc->readable) { + fc->readable = false; + } + } + + struct dirent *e; + while (NULL != (e = readdir(dir))) { + if ((0 == strcmp(e->d_name, ".")) || (0 == strcmp(e->d_name, ".."))) + continue; + if (!bc_str_ends_with(e->d_name, source_ext)) + continue; + char *tmp = bc_strdup_printf("%s/%s", posts_dir, e->d_name); + + // trick 2: if the file context exists in the index, just set it as + // readable + bm_filectx_t *fc = NULL; + if (reloading) { + for (bc_slist_t *t = ctx->posts_fctx; t != NULL; t = t->next) { + bm_filectx_t *fct = t->data; + if (0 == strcmp(fct->short_path, tmp)) { + fc = fct; + break; + } + } + } + if (fc != NULL) { + fc->readable = true; + bm_filectx_reload(fc); + } + else { + e->d_name[strlen(e->d_name) - strlen(source_ext)] = 0; + fc = bm_filectx_new(ctx, tmp, e->d_name, NULL); + ctx->posts_fctx = bc_slist_append(ctx->posts_fctx, fc); + } + free(tmp); + } + + // trick 3: delete the unreadable file contexts + ctx->posts_deleted = false; + if (reloading) { + for (bc_slist_t *tmp = ctx->posts_fctx; tmp != NULL;) { + bm_filectx_t *fc = tmp->data; + if (!fc->readable) { + bc_slist_t *next = tmp->next; + ctx->posts_fctx = bc_slist_remove(ctx->posts_fctx, tmp, + (bc_free_func_t) bm_filectx_free); + tmp = next; + ctx->posts_deleted = true; + } + else { + tmp = tmp->next; + } + } + } + + closedir(dir); + free(posts_dir); +} + + void bm_ctx_free_internal(bm_ctx_t *ctx) { diff --git a/src/blogc-make/ctx.h b/src/blogc-make/ctx.h index a66d51c..43284a5 100644 --- a/src/blogc-make/ctx.h +++ b/src/blogc-make/ctx.h @@ -63,8 +63,10 @@ typedef struct { bm_filectx_t *listing_entry_fctx; bc_slist_t *posts_fctx; + bool posts_deleted; bc_slist_t *pages_fctx; bc_slist_t *copy_fctx; + } bm_ctx_t; bm_filectx_t* bm_filectx_new(bm_ctx_t *ctx, const char *filename, const char *slug, @@ -76,6 +78,7 @@ void bm_filectx_free(bm_filectx_t *fctx); bm_ctx_t* bm_ctx_new(bm_ctx_t *base, const char *settings_file, const char *argv0, bc_error_t **err); bool bm_ctx_reload(bm_ctx_t **ctx); +void bm_ctx_autoload_posts(bm_ctx_t *ctx); void bm_ctx_free_internal(bm_ctx_t *ctx); void bm_ctx_free(bm_ctx_t *ctx); const char* bm_ctx_settings_lookup(bm_ctx_t *ctx, const char *key); diff --git a/src/blogc-make/rules.c b/src/blogc-make/rules.c index 96cf51d..f42b99a 100644 --- a/src/blogc-make/rules.c +++ b/src/blogc-make/rules.c @@ -32,7 +32,9 @@ posts_ordering(bm_ctx_t *ctx, bc_trie_t *variables, const char *variable) const char *value = bm_ctx_settings_lookup_str(ctx, variable); bool asc = 0 == strcasecmp(value, "asc"); - bool sort = bc_str_to_bool(bm_ctx_settings_lookup(ctx, "posts_sort")); + bool posts_autoload = bc_str_to_bool(bm_ctx_settings_lookup(ctx, "posts_autoload")); + bool posts_sort = bc_str_to_bool(bm_ctx_settings_lookup(ctx, "posts_sort")); + bool sort = posts_sort || posts_autoload; if (sort) { bc_trie_insert(variables, "FILTER_SORT", bc_strdup("1")); @@ -75,7 +77,7 @@ posts_pagination_enabled(bm_ctx_t *ctx, const char *variable) static bc_slist_t* index_outputlist(bm_ctx_t *ctx) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return NULL; if (!posts_pagination_enabled(ctx, "posts_per_page")) @@ -97,7 +99,7 @@ index_outputlist(bm_ctx_t *ctx) static int index_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return 0; int rv = 0; @@ -114,7 +116,8 @@ index_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) bm_filectx_t *fctx = l->data; if (fctx == NULL) continue; - if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, + if (ctx->posts_deleted || + bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, ctx->listing_entry_fctx, ctx->main_template_fctx, fctx, false)) { rv = bm_exec_blogc(ctx, variables, NULL, true, ctx->listing_entry_fctx, @@ -135,7 +138,7 @@ index_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) static bc_slist_t* atom_outputlist(bm_ctx_t *ctx) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return NULL; if (!posts_pagination_enabled(ctx, "atom_posts_per_page")) @@ -157,7 +160,7 @@ atom_outputlist(bm_ctx_t *ctx) static int atom_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return 0; int rv = 0; @@ -173,7 +176,8 @@ atom_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) bm_filectx_t *fctx = l->data; if (fctx == NULL) continue; - if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, NULL, NULL, + if (ctx->posts_deleted || + bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, NULL, NULL, fctx, false)) { rv = bm_exec_blogc(ctx, variables, NULL, true, NULL, ctx->atom_template_fctx, @@ -194,7 +198,7 @@ atom_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) static bc_slist_t* atom_tags_outputlist(bm_ctx_t *ctx) { - if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL || ctx->settings->tags == NULL) return NULL; if (!posts_pagination_enabled(ctx, "atom_posts_per_page")) @@ -218,7 +222,7 @@ atom_tags_outputlist(bm_ctx_t *ctx) static int atom_tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) { - if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL || ctx->settings->tags == NULL) return 0; int rv = 0; @@ -239,7 +243,8 @@ atom_tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) bc_trie_insert(variables, "FILTER_TAG", bc_strdup(ctx->settings->tags[i])); - if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, NULL, NULL, + if (ctx->posts_deleted || + bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, NULL, NULL, fctx, false)) { rv = bm_exec_blogc(ctx, variables, NULL, true, NULL, ctx->atom_template_fctx, @@ -260,7 +265,7 @@ atom_tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) static bc_slist_t* pagination_outputlist(bm_ctx_t *ctx) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return NULL; // not using posts_pagination_enabled() here because we need to calculate @@ -293,7 +298,7 @@ pagination_outputlist(bm_ctx_t *ctx) static int pagination_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return 0; int rv = 0; @@ -315,7 +320,8 @@ pagination_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) if (fctx == NULL) continue; bc_trie_insert(variables, "FILTER_PAGE", bc_strdup_printf("%zu", page)); - if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, + if (ctx->posts_deleted || + bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, ctx->listing_entry_fctx, ctx->main_template_fctx, fctx, false)) { rv = bm_exec_blogc(ctx, variables, NULL, true, ctx->listing_entry_fctx, @@ -336,7 +342,7 @@ pagination_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) static bc_slist_t* posts_outputlist(bm_ctx_t *ctx) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return NULL; bc_slist_t *rv = NULL; @@ -344,9 +350,10 @@ posts_outputlist(bm_ctx_t *ctx) const char *post_prefix = bm_ctx_settings_lookup(ctx, "post_prefix"); const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext"); - for (size_t i = 0; ctx->settings->posts[i] != NULL; i++) { + for (bc_slist_t *l = ctx->posts_fctx; l != NULL; l = l->next) { + bm_filectx_t *fc = l->data; char *f = bm_generate_filename(ctx->short_output_dir, post_prefix, - ctx->settings->posts[i], html_ext); + fc->slug, html_ext); rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL)); free(f); } @@ -357,7 +364,7 @@ posts_outputlist(bm_ctx_t *ctx) static int posts_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) { - if (ctx == NULL || ctx->settings->posts == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL) return 0; int rv = 0; @@ -403,7 +410,7 @@ posts_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) static bc_slist_t* tags_outputlist(bm_ctx_t *ctx) { - if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL || ctx->settings->tags == NULL) return NULL; if (!posts_pagination_enabled(ctx, "posts_per_page")) @@ -427,7 +434,7 @@ tags_outputlist(bm_ctx_t *ctx) static int tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) { - if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL) + if (ctx == NULL || ctx->posts_fctx == NULL || ctx->settings->tags == NULL) return 0; int rv = 0; @@ -449,7 +456,8 @@ tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args) bc_trie_insert(variables, "FILTER_TAG", bc_strdup(ctx->settings->tags[i])); - if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, + if (ctx->posts_deleted || + bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, ctx->listing_entry_fctx, ctx->main_template_fctx, fctx, false)) { rv = bm_exec_blogc(ctx, variables, NULL, true, ctx->listing_entry_fctx, diff --git a/src/blogc-make/settings.c b/src/blogc-make/settings.c index be976e3..2f56d9c 100644 --- a/src/blogc-make/settings.c +++ b/src/blogc-make/settings.c @@ -28,6 +28,7 @@ static const struct default_settings_map { {"main_template", "main.tmpl"}, {"source_ext", ".txt"}, {"listing_entry", NULL}, + {"posts_autoload", NULL}, {"posts_sort", NULL}, // pagination -- cgit v1.2.3-18-g5258