aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2017-02-24 23:15:28 +0100
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2017-02-24 23:15:28 +0100
commitfb27e8ed5030e6b5aa8df33cc4d347eacaef76ba (patch)
tree35f634c605ae01c195408ffb4334da43b89f4c07
parent144f49bdee2dd7d29748d2c3d2e3c0e5cfbfa34d (diff)
downloadblogc-fb27e8ed5030e6b5aa8df33cc4d347eacaef76ba.tar.gz
blogc-fb27e8ed5030e6b5aa8df33cc4d347eacaef76ba.tar.bz2
blogc-fb27e8ed5030e6b5aa8df33cc4d347eacaef76ba.zip
make: parse runserver arguments from cli, instead of env
this is some over-optimized parser, to celebrate #cloudbleed :D
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am19
-rw-r--r--src/blogc-make/exec.c18
-rw-r--r--src/blogc-make/exec.h3
-rw-r--r--src/blogc-make/main.c3
-rw-r--r--src/blogc-make/rules.c103
-rw-r--r--src/blogc-make/rules.h6
-rw-r--r--tests/blogc-make/check_rules.c104
8 files changed, 217 insertions, 40 deletions
diff --git a/.gitignore b/.gitignore
index b6ded60..a530082 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,6 +70,7 @@ blogc*.html
/tests/blogc-make/check_atom
/tests/blogc-make/check_blogc_make.sh
/tests/blogc-make/check_exec
+/tests/blogc-make/check_rules
/tests/blogc-make/check_settings
/tests/blogc-runserver/check_httpd_utils
/tests/blogc-runserver/check_mime
diff --git a/Makefile.am b/Makefile.am
index d1317d9..70b7b92 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -758,6 +758,7 @@ if BUILD_MAKE_LIB
check_PROGRAMS += \
tests/blogc-make/check_atom \
tests/blogc-make/check_exec \
+ tests/blogc-make/check_rules \
tests/blogc-make/check_settings \
$(NULL)
@@ -797,6 +798,24 @@ tests_blogc_make_check_exec_LDADD = \
libblogc_common.la \
$(NULL)
+tests_blogc_make_check_rules_SOURCES = \
+ tests/blogc-make/check_rules.c \
+ $(NULL)
+
+tests_blogc_make_check_rules_CFLAGS = \
+ $(CMOCKA_CFLAGS) \
+ $(NULL)
+
+tests_blogc_make_check_rules_LDFLAGS = \
+ -no-install \
+ $(NULL)
+
+tests_blogc_make_check_rules_LDADD = \
+ $(CMOCKA_LIBS) \
+ libblogc_make.la \
+ libblogc_common.la \
+ $(NULL)
+
tests_blogc_make_check_settings_SOURCES = \
tests/blogc-make/check_settings.c \
$(NULL)
diff --git a/src/blogc-make/exec.c b/src/blogc-make/exec.c
index dafa6cb..bbba573 100644
--- a/src/blogc-make/exec.c
+++ b/src/blogc-make/exec.c
@@ -305,7 +305,8 @@ bm_exec_blogc(bm_settings_t *settings, bc_trie_t *variables, bool listing,
int
-bm_exec_blogc_runserver(const char *output_dir, bool verbose)
+bm_exec_blogc_runserver(const char *output_dir, const char *host,
+ const char *port, const char *threads, bool verbose)
{
bc_string_t *cmd = bc_string_new();
@@ -320,23 +321,20 @@ bm_exec_blogc_runserver(const char *output_dir, bool verbose)
bc_string_append(cmd, "blogc-runserver");
}
- const char *runserver_host_tmp = getenv("RUNSERVER_HOST");
- if (runserver_host_tmp != NULL) {
- char *tmp = bc_shell_quote(runserver_host_tmp);
+ if (host != NULL) {
+ char *tmp = bc_shell_quote(host);
bc_string_append_printf(cmd, " -t %s", tmp);
free(tmp);
}
- const char *runserver_port_tmp = getenv("RUNSERVER_PORT");
- if (runserver_port_tmp != NULL) {
- char *tmp = bc_shell_quote(runserver_port_tmp);
+ if (port != NULL) {
+ char *tmp = bc_shell_quote(port);
bc_string_append_printf(cmd, " -p %s", tmp);
free(tmp);
}
- const char *runserver_threads_tmp = getenv("RUNSERVER_THREADS");
- if (runserver_threads_tmp != NULL) {
- char *tmp = bc_shell_quote(runserver_threads_tmp);
+ if (threads != NULL) {
+ char *tmp = bc_shell_quote(threads);
bc_string_append_printf(cmd, " -m %s", tmp);
free(tmp);
}
diff --git a/src/blogc-make/exec.h b/src/blogc-make/exec.h
index 8c42c9f..970befa 100644
--- a/src/blogc-make/exec.h
+++ b/src/blogc-make/exec.h
@@ -22,6 +22,7 @@ char* bm_exec_build_blogc_cmd(bm_settings_t *settings, bc_trie_t *variables,
int bm_exec_blogc(bm_settings_t *settings, bc_trie_t *variables, bool listing,
bm_filectx_t *template, bm_filectx_t *output, bc_slist_t *sources,
bool verbose, bool only_first_source);
-int bm_exec_blogc_runserver(const char *output_dir, bool verbose);
+int bm_exec_blogc_runserver(const char *output_dir, const char *host,
+ const char *port, const char *threads, bool verbose);
#endif /* _MAKE_EXEC_H */
diff --git a/src/blogc-make/main.c b/src/blogc-make/main.c
index 98d4cc7..5f6a1e9 100644
--- a/src/blogc-make/main.c
+++ b/src/blogc-make/main.c
@@ -29,7 +29,8 @@ print_help(void)
" - A simple build tool for blogc.\n"
"\n"
"positional arguments:\n"
- " RULE build rule(s) to run (default: all)\n"
+ " RULE build rule(s) to run. can include comma-separated\n"
+ " key-value pairs of rule settings (default: all)\n"
"\n"
"optional arguments:\n"
" -h show this help message and exit\n"
diff --git a/src/blogc-make/rules.c b/src/blogc-make/rules.c
index 9f5d9bc..36570f1 100644
--- a/src/blogc-make/rules.c
+++ b/src/blogc-make/rules.c
@@ -48,7 +48,7 @@ index_outputlist(bm_ctx_t *ctx)
}
static int
-index_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+index_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->posts == NULL)
return 0;
@@ -106,7 +106,7 @@ atom_outputlist(bm_ctx_t *ctx)
}
static int
-atom_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+atom_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->posts == NULL)
return 0;
@@ -167,7 +167,7 @@ atom_tags_outputlist(bm_ctx_t *ctx)
}
static int
-atom_tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+atom_tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
return 0;
@@ -241,7 +241,7 @@ pagination_outputlist(bm_ctx_t *ctx)
}
static int
-pagination_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+pagination_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->posts == NULL)
return 0;
@@ -304,7 +304,7 @@ posts_outputlist(bm_ctx_t *ctx)
}
static int
-posts_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+posts_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->posts == NULL)
return 0;
@@ -366,7 +366,7 @@ tags_outputlist(bm_ctx_t *ctx)
}
static int
-tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
return 0;
@@ -435,7 +435,7 @@ pages_outputlist(bm_ctx_t *ctx)
}
static int
-pages_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+pages_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->pages == NULL)
return 0;
@@ -491,7 +491,7 @@ copy_outputlist(bm_ctx_t *ctx)
}
static int
-copy_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+copy_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
if (ctx == NULL || ctx->settings->copy == NULL)
return 0;
@@ -527,7 +527,7 @@ clean_outputlist(bm_ctx_t *ctx)
}
static int
-clean_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+clean_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
int rv = 0;
@@ -551,7 +551,8 @@ clean_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
}
-static int all_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose);
+static int all_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args,
+ bool verbose);
// RUNSERVER RULE
@@ -583,7 +584,7 @@ runserver_thread(void *arg)
"reloader disabled!\n");
goto runserver_cleanup;
}
- if (0 != all_exec(args->ctx, NULL, args->verbose)) {
+ if (0 != all_exec(args->ctx, NULL, NULL, args->verbose)) {
fprintf(stderr, "blogc-make: error: failed to rebuild website. "
"reloader disabled!\n");
goto runserver_cleanup;
@@ -599,20 +600,20 @@ runserver_cleanup:
}
static int
-runserver_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+runserver_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
// first 'all' call is syncronous, to do a 'sanity check'
- int rv = all_exec(ctx, NULL, verbose);
+ int rv = all_exec(ctx, NULL, NULL, verbose);
if (rv != 0)
return rv;
- runserver_args_t *args = bc_malloc(sizeof(runserver_args_t));
- args->ctx = ctx;
- args->verbose = verbose;
+ runserver_args_t *r_args = bc_malloc(sizeof(runserver_args_t));
+ r_args->ctx = ctx;
+ r_args->verbose = verbose;
pthread_t thread;
- if (0 != pthread_create(&thread, NULL, runserver_thread, args)) {
+ if (0 != pthread_create(&thread, NULL, runserver_thread, r_args)) {
fprintf(stderr, "blogc-make: error: failed to create blogc-runserver "
"thread!\n");
return 3;
@@ -624,7 +625,8 @@ runserver_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
return 3;
}
- bm_exec_blogc_runserver(ctx->output_dir, verbose);
+ bm_exec_blogc_runserver(ctx->output_dir, bc_trie_lookup(args, "host"),
+ bc_trie_lookup(args, "port"), bc_trie_lookup(args, "threads"), verbose);
return 0;
}
@@ -714,14 +716,14 @@ const bm_rule_t rules[] = {
// ALL RULE
static int
-all_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
+all_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args, bool verbose)
{
for (size_t i = 0; rules[i].name != NULL; i++) {
if (!rules[i].generate_files) {
continue;
}
- int rv = bm_rule_execute(ctx, &(rules[i]), verbose);
+ int rv = bm_rule_execute(ctx, &(rules[i]), NULL, verbose);
if (rv != 0) {
return rv;
}
@@ -730,6 +732,36 @@ all_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bool verbose)
}
+bc_trie_t*
+bm_rule_parse_args(const char *sep)
+{
+ if (sep == NULL || *sep == '\0' || *sep != ':')
+ return NULL;
+
+ bc_trie_t *rv = bc_trie_new(free);
+ char *end = (char*) sep + 1;
+ char *kv_sep;
+ while (NULL != (kv_sep = strchr(end, '='))) {
+ char *key = bc_strndup(end, kv_sep - end);
+ end = kv_sep + 1;
+ kv_sep = strchr(end, ',');
+ if (kv_sep == NULL)
+ kv_sep = strchr(end, '\0');
+ char *value = bc_strndup(end, kv_sep - end);
+ bc_trie_insert(rv, key, value);
+ free(key);
+ if (*kv_sep == '\0')
+ break;
+ end = kv_sep + 1;
+ }
+ if (kv_sep == NULL) {
+ bc_trie_free(rv);
+ return NULL;
+ }
+ return rv;
+}
+
+
int
bm_rule_executor(bm_ctx_t *ctx, bc_slist_t *rule_list, bool verbose)
{
@@ -740,18 +772,36 @@ bm_rule_executor(bm_ctx_t *ctx, bc_slist_t *rule_list, bool verbose)
int rv = 0;
for (bc_slist_t *l = rule_list; l != NULL; l = l->next) {
+
+ char *rule_str = l->data;
+ char *sep = strchr(rule_str, ':');
+
+ bc_trie_t *args = NULL;
+ if (sep == NULL) {
+ sep = strchr(rule_str, '\0');
+ }
+ else {
+ args = bm_rule_parse_args(sep);
+ if (args == NULL) {
+ fprintf(stderr, "blogc-make: warning: failed to parse rule "
+ "arguments, ignoring: %s\n", rule_str);
+ }
+ }
+
rule = NULL;
for (size_t i = 0; rules[i].name != NULL; i++) {
- if (0 == strcmp((char*) l->data, rules[i].name)) {
+ if (strlen(rules[i].name) < (sep - rule_str))
+ continue;
+ if (0 == strncmp(rule_str, rules[i].name, sep - rule_str)) {
rule = &(rules[i]);
- rv = bm_rule_execute(ctx, rule, verbose);
+ rv = bm_rule_execute(ctx, rule, args, verbose);
if (rv != 0)
return rv;
}
}
if (rule == NULL) {
- fprintf(stderr, "blogc-make: error: rule not found: %s\n",
- (char*) l->data);
+ fprintf(stderr, "blogc-make: error: rule not found: %.*s\n",
+ (int) (sep - rule_str), rule_str);
rv = 3;
}
}
@@ -761,7 +811,8 @@ bm_rule_executor(bm_ctx_t *ctx, bc_slist_t *rule_list, bool verbose)
int
-bm_rule_execute(bm_ctx_t *ctx, const bm_rule_t *rule, bool verbose)
+bm_rule_execute(bm_ctx_t *ctx, const bm_rule_t *rule, bc_trie_t *args,
+ bool verbose)
{
if (ctx == NULL || rule == NULL)
return 3;
@@ -771,7 +822,7 @@ bm_rule_execute(bm_ctx_t *ctx, const bm_rule_t *rule, bool verbose)
outputs = rule->outputlist_func(ctx);
}
- int rv = rule->exec_func(ctx, outputs, verbose);
+ int rv = rule->exec_func(ctx, outputs, args, verbose);
bc_slist_free_full(outputs, (bc_free_func_t) bm_filectx_free);
diff --git a/src/blogc-make/rules.h b/src/blogc-make/rules.h
index b39e7be..7a15d45 100644
--- a/src/blogc-make/rules.h
+++ b/src/blogc-make/rules.h
@@ -15,7 +15,7 @@
typedef bc_slist_t* (*bm_rule_outputlist_func_t) (bm_ctx_t *ctx);
typedef int (*bm_rule_exec_func_t) (bm_ctx_t *ctx, bc_slist_t *outputs,
- bool verbose);
+ bc_trie_t *args, bool verbose);
typedef struct {
const char *name;
@@ -25,8 +25,10 @@ typedef struct {
bool generate_files;
} bm_rule_t;
+bc_trie_t* bm_rule_parse_args(const char *sep);
int bm_rule_executor(bm_ctx_t *ctx, bc_slist_t *rule_list, bool verbose);
-int bm_rule_execute(bm_ctx_t *ctx, const bm_rule_t *rule, bool verbose);
+int bm_rule_execute(bm_ctx_t *ctx, const bm_rule_t *rule, bc_trie_t *args,
+ bool verbose);
bool bm_rule_need_rebuild(bc_slist_t *sources, bm_filectx_t *settings,
bm_filectx_t *template, bm_filectx_t *output, bool only_first_source);
bc_slist_t* bm_rule_list_built_files(bm_ctx_t *ctx);
diff --git a/tests/blogc-make/check_rules.c b/tests/blogc-make/check_rules.c
new file mode 100644
index 0000000..0ef8be7
--- /dev/null
+++ b/tests/blogc-make/check_rules.c
@@ -0,0 +1,104 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2015-2017 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../src/blogc-make/rules.h"
+#include "../../src/common/utils.h"
+
+
+static void
+test_rule_parse_args(void **state)
+{
+ bc_trie_t *t = bm_rule_parse_args("bola:foo=" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 1);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=bar" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 1);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "bar");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=,baz=lol" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 2);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "");
+ assert_string_equal(bc_trie_lookup(t, "baz"), "lol");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=bar,baz=" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 2);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "bar");
+ assert_string_equal(bc_trie_lookup(t, "baz"), "");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=bar,baz=lol" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 2);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "bar");
+ assert_string_equal(bc_trie_lookup(t, "baz"), "lol");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=,baz=lol,asd=qwe" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 3);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "");
+ assert_string_equal(bc_trie_lookup(t, "baz"), "lol");
+ assert_string_equal(bc_trie_lookup(t, "asd"), "qwe");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=bar,baz=,asd=qwe" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 3);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "bar");
+ assert_string_equal(bc_trie_lookup(t, "baz"), "");
+ assert_string_equal(bc_trie_lookup(t, "asd"), "qwe");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=bar,baz=lol,asd=" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 3);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "bar");
+ assert_string_equal(bc_trie_lookup(t, "baz"), "lol");
+ assert_string_equal(bc_trie_lookup(t, "asd"), "");
+ bc_trie_free(t);
+ t = bm_rule_parse_args("bola:foo=bar,baz=lol,asd=qwe" + 4);
+ assert_non_null(t);
+ assert_int_equal(bc_trie_size(t), 3);
+ assert_string_equal(bc_trie_lookup(t, "foo"), "bar");
+ assert_string_equal(bc_trie_lookup(t, "baz"), "lol");
+ assert_string_equal(bc_trie_lookup(t, "asd"), "qwe");
+ bc_trie_free(t);
+}
+
+
+static void
+test_rule_parse_args_error(void **state)
+{
+ assert_null(bm_rule_parse_args(NULL));
+ assert_null(bm_rule_parse_args("bola" + 4));
+ assert_null(bm_rule_parse_args("bola:" + 4));
+ assert_null(bm_rule_parse_args("bola:asd" + 4));
+ assert_null(bm_rule_parse_args("bola:asd=foo,lol" + 4));
+ assert_null(bm_rule_parse_args("bola:asd=foo,qwe=bar,lol" + 4));
+ assert_null(bm_rule_parse_args("bolaasd" + 4));
+}
+
+
+int
+main(void)
+{
+ const UnitTest tests[] = {
+ unit_test(test_rule_parse_args),
+ unit_test(test_rule_parse_args_error),
+ };
+ return run_tests(tests);
+}