diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/blogc-make/ctx.c | 108 | ||||
| -rw-r--r-- | src/blogc-make/ctx.h | 3 | ||||
| -rw-r--r-- | src/blogc-make/rules.c | 48 | ||||
| -rw-r--r-- | src/blogc-make/settings.c | 1 | 
4 files changed, 136 insertions, 24 deletions
| 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 <libgen.h>  #include <limits.h>  #include <time.h> +#include <stdio.h>  #include <stdlib.h>  #include <stdbool.h>  #include <string.h> @@ -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); @@ -342,6 +352,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)  {      if (ctx == NULL) 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 | 
