From 13be5bd50238daa2be6b42104ba20aeea427655b Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Tue, 4 Oct 2016 23:58:10 +0200 Subject: git-receiver: splitted and tested pre-receive input parser --- .gitignore | 2 + Makefile.am | 47 ++++++++++ src/blogc-git-receiver/pre-receive-parser.c | 77 ++++++++++++++++ src/blogc-git-receiver/pre-receive-parser.h | 14 +++ src/blogc-git-receiver/pre-receive.c | 91 ++----------------- src/common/stdin.c | 23 +++++ src/common/stdin.h | 14 +++ .../blogc-git-receiver/check_pre_receive_parser.c | 101 +++++++++++++++++++++ tests/common/check_stdin.c | 53 +++++++++++ 9 files changed, 341 insertions(+), 81 deletions(-) create mode 100644 src/blogc-git-receiver/pre-receive-parser.c create mode 100644 src/blogc-git-receiver/pre-receive-parser.h create mode 100644 src/common/stdin.c create mode 100644 src/common/stdin.h create mode 100644 tests/blogc-git-receiver/check_pre_receive_parser.c create mode 100644 tests/common/check_stdin.c diff --git a/.gitignore b/.gitignore index a222ebe..af2b5d8 100644 --- a/.gitignore +++ b/.gitignore @@ -57,10 +57,12 @@ blogc*.html /tests/blogc/check_renderer /tests/blogc/check_source_parser /tests/blogc/check_template_parser +/tests/blogc-git-receiver/check_pre_receive_parser /tests/blogc-runserver/check_httpd_utils /tests/blogc-runserver/check_mime /tests/common/check_config_parser /tests/common/check_error +/tests/common/check_stdin /tests/common/check_utf8 /tests/common/check_utils diff --git a/Makefile.am b/Makefile.am index ef4e282..fff49b9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,6 +41,7 @@ noinst_HEADERS = \ src/blogc/template-parser.h \ src/blogc-git-receiver/post-receive.h \ src/blogc-git-receiver/pre-receive.h \ + src/blogc-git-receiver/pre-receive-parser.h \ src/blogc-git-receiver/shell.h \ src/blogc-runserver/httpd.h \ src/blogc-runserver/httpd-utils.h \ @@ -48,6 +49,7 @@ noinst_HEADERS = \ src/common/config-parser.h \ src/common/error.h \ src/common/file.h \ + src/common/stdin.h \ src/common/utf8.h \ src/common/utils.h \ $(NULL) @@ -110,6 +112,7 @@ libblogc_common_la_SOURCES = \ src/common/config-parser.c \ src/common/error.c \ src/common/file.c \ + src/common/stdin.c \ src/common/utf8.c \ src/common/utils.c \ $(NULL) @@ -151,6 +154,7 @@ blogc_git_receiver_LDADD = \ libblogc_git_receiver_la_SOURCES = \ src/blogc-git-receiver/post-receive.c \ src/blogc-git-receiver/pre-receive.c \ + src/blogc-git-receiver/pre-receive-parser.c \ src/blogc-git-receiver/shell.c \ $(NULL) @@ -319,6 +323,7 @@ check_PROGRAMS += \ tests/blogc/check_template_parser \ tests/common/check_config_parser \ tests/common/check_error \ + tests/common/check_stdin \ tests/common/check_utf8 \ tests/common/check_utils \ $(NULL) @@ -466,6 +471,24 @@ tests_common_check_error_LDADD = \ libblogc_common.la \ $(NULL) +tests_common_check_stdin_SOURCES = \ + tests/common/check_stdin.c \ + $(NULL) + +tests_common_check_stdin_CFLAGS = \ + $(CMOCKA_CFLAGS) \ + $(NULL) + +tests_common_check_stdin_LDFLAGS = \ + -no-install \ + -Wl,--wrap=fgetc \ + $(NULL) + +tests_common_check_stdin_LDADD = \ + $(CMOCKA_LIBS) \ + libblogc_common.la \ + $(NULL) + tests_common_check_utf8_SOURCES = \ tests/common/check_utf8.c \ $(NULL) @@ -545,6 +568,30 @@ tests_blogc_runserver_check_mime_LDADD = \ $(NULL) endif +if BUILD_GIT_RECEIVER +check_PROGRAMS += \ + tests/blogc-git-receiver/check_pre_receive_parser \ + $(NULL) + +tests_blogc_git_receiver_check_pre_receive_parser_SOURCES = \ + tests/blogc-git-receiver/check_pre_receive_parser.c \ + $(NULL) + +tests_blogc_git_receiver_check_pre_receive_parser_CFLAGS = \ + $(CMOCKA_CFLAGS) \ + $(NULL) + +tests_blogc_git_receiver_check_pre_receive_parser_LDFLAGS = \ + -no-install \ + $(NULL) + +tests_blogc_git_receiver_check_pre_receive_parser_LDADD = \ + $(CMOCKA_LIBS) \ + libblogc_git_receiver.la \ + libblogc_common.la \ + $(NULL) +endif + endif TESTS = \ diff --git a/src/blogc-git-receiver/pre-receive-parser.c b/src/blogc-git-receiver/pre-receive-parser.c new file mode 100644 index 0000000..a842a9d --- /dev/null +++ b/src/blogc-git-receiver/pre-receive-parser.c @@ -0,0 +1,77 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include +#include +#include "../common/utils.h" +#include "pre-receive-parser.h" + +typedef enum { + START_OLD = 1, + OLD, + START_NEW, + NEW, + START_REF, + REF +} input_state_t; + + +char* +bgr_pre_receive_parse(const char *input) +{ + input_state_t state = START_OLD; + size_t start = 0; + size_t start_new = 0; + size_t input_len = strlen(input); + + for (size_t current = 0; current < input_len; current++) { + + char c = input[current]; + + switch (state) { + case START_OLD: + start = current; + state = OLD; + break; + case OLD: + if (c != ' ') + break; + // no need to store old + state = START_NEW; + break; + case START_NEW: + start = current; + state = NEW; + break; + case NEW: + if (c != ' ') + break; + state = START_REF; + start_new = start; + break; + case START_REF: + start = current; + state = REF; + break; + case REF: + if (c != '\n') + break; + state = START_OLD; + // we just care about a ref (refs/heads/master), everything + // else is disposable :) + if ((current - start == 17) && + (0 == strncmp("refs/heads/master", input + start, 17))) + { + return bc_strndup(input + start_new, start - 1 - start_new); + } + break; + } + } + + return NULL; +} diff --git a/src/blogc-git-receiver/pre-receive-parser.h b/src/blogc-git-receiver/pre-receive-parser.h new file mode 100644 index 0000000..3a605da --- /dev/null +++ b/src/blogc-git-receiver/pre-receive-parser.h @@ -0,0 +1,14 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifndef _PRE_RECEIVE_PARSER_H +#define _PRE_RECEIVE_PARSER_H + +char* bgr_pre_receive_parse(const char *input); + +#endif /* _PRE_RECEIVE_PARSER_H */ diff --git a/src/blogc-git-receiver/pre-receive.c b/src/blogc-git-receiver/pre-receive.c index 8c35537..ca239da 100644 --- a/src/blogc-git-receiver/pre-receive.c +++ b/src/blogc-git-receiver/pre-receive.c @@ -17,12 +17,10 @@ #include #include #include - #include "../common/utils.h" - -#ifndef BUFFER_SIZE -#define BUFFER_SIZE 4096 -#endif +#include "../common/stdin.h" +#include "pre-receive-parser.h" +#include "pre-receive.h" static unsigned int @@ -91,93 +89,26 @@ rmdir_recursive(const char *dir) } -typedef enum { - START_OLD = 1, - OLD, - START_NEW, - NEW, - START_REF, - REF -} input_state_t; - - int bgr_pre_receive_hook(int argc, char *argv[]) { - int c; - char buffer[BUFFER_SIZE]; - - input_state_t state = START_OLD; - size_t i = 0; - size_t start = 0; - int rv = 0; - char *new = NULL; - char *master = NULL; + char buffer[4096]; - while (EOF != (c = getc(stdin))) { - - buffer[i] = (char) c; - - switch (state) { - case START_OLD: - start = i; - state = OLD; - break; - case OLD: - if (c != ' ') - break; - // no need to store old - state = START_NEW; - break; - case START_NEW: - start = i; - state = NEW; - break; - case NEW: - if (c != ' ') - break; - state = START_REF; - new = strndup(buffer + start, i - start); - break; - case START_REF: - start = i; - state = REF; - break; - case REF: - if (c != '\n') - break; - state = START_OLD; - // we just care about a ref (refs/heads/master), everything - // else is disposable :) - if (!((i - start == 17) && - (0 == strncmp("refs/heads/master", buffer + start, 17)))) - { - free(new); - new = NULL; - break; - } - master = new; - break; - } - - if (++i >= BUFFER_SIZE) { - fprintf(stderr, "error: pre-receive hook payload is too big.\n"); - rv = 1; - goto cleanup2; - } - } + char *input = bc_stdin_read(); + char *master = bgr_pre_receive_parse(input); + free(input); if (master == NULL) { fprintf(stderr, "warning: no reference to master branch found. " "nothing to deploy.\n"); - goto cleanup2; + return rv; } char *repo_dir = NULL; char *output_dir = NULL; - if (NULL == getcwd(buffer, BUFFER_SIZE)) { + if (NULL == getcwd(buffer, sizeof(buffer))) { fprintf(stderr, "error: failed to get repository remote path: %s\n", strerror(errno)); rv = 1; @@ -247,7 +178,7 @@ bgr_pre_receive_hook(int argc, char *argv[]) } char *htdocs_sym = NULL; - ssize_t htdocs_sym_len = readlink("htdocs", buffer, BUFFER_SIZE); + ssize_t htdocs_sym_len = readlink("htdocs", buffer, sizeof(buffer)); if (0 < htdocs_sym_len) { if (0 != unlink("htdocs")) { fprintf(stderr, "error: failed to remove symlink (%s/htdocs): %s\n", @@ -275,7 +206,5 @@ cleanup: free(output_dir); rmdir_recursive(dir); free(repo_dir); -cleanup2: - free(new); return rv; } diff --git a/src/common/stdin.c b/src/common/stdin.c new file mode 100644 index 0000000..2664c3e --- /dev/null +++ b/src/common/stdin.c @@ -0,0 +1,23 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include +#include "utils.h" +#include "stdin.h" + + +// splitted in single file to make it easier to test +char* +bc_stdin_read(void) +{ + int c; + bc_string_t *rv = bc_string_new(); + while (EOF != (c = fgetc(stdin))) + bc_string_append_c(rv, c); + return bc_string_free(rv, false); +} diff --git a/src/common/stdin.h b/src/common/stdin.h new file mode 100644 index 0000000..ebf042d --- /dev/null +++ b/src/common/stdin.h @@ -0,0 +1,14 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifndef _STDIN_H +#define _STDIN_H + +char* bc_stdin_read(void); + +#endif /* _STDIN_H */ diff --git a/tests/blogc-git-receiver/check_pre_receive_parser.c b/tests/blogc-git-receiver/check_pre_receive_parser.c new file mode 100644 index 0000000..0c716fa --- /dev/null +++ b/tests/blogc-git-receiver/check_pre_receive_parser.c @@ -0,0 +1,101 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include +#include +#include +#include +#include +#include "../../src/blogc-git-receiver/pre-receive-parser.h" + + +static void +test_pre_receive_parse(void **state) +{ + assert_null(bgr_pre_receive_parse("")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 ")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545f3")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545f3 ")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545f3 " + "refs/heads/lol")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545f3 " + "refs/heads/lol")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545f3 " + "refs/heads/master")); + assert_null(bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545f3 " + "refs/heads/master asd\n")); + char *t; + t = bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545f3 " + "refs/heads/master\n"); + assert_non_null(t); + assert_string_equal(t, "3fff4bb3172f77b292b0c913749e81bedd3545f3"); + free(t); + t = bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545fa " + "refs/heads/master\n" + "4f1f932f6ef6d6c9770266775c2db072964d7a63 " + "3fff4bb3172f77b292b0c913749e81bedd3545f4 " + "refs/heads/bola\n" + ); + assert_non_null(t); + assert_string_equal(t, "3fff4bb3172f77b292b0c913749e81bedd3545fa"); + free(t); + t = bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a63 " + "3fff4bb3172f77b292b0c913749e81bedd3545f4 " + "refs/heads/bola\n" + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545fb " + "refs/heads/master\n" + ); + assert_non_null(t); + assert_string_equal(t, "3fff4bb3172f77b292b0c913749e81bedd3545fb"); + free(t); + t = bgr_pre_receive_parse( + "4f1f932f6ef6d6c9770266775c2db072964d7a63 " + "3fff4bb3172f77b292b0c913749e81bedd3545f4 " + "refs/heads/bola\n" + "4f1f932f6ef6d6c9770266775c2db072964d7a62 " + "3fff4bb3172f77b292b0c913749e81bedd3545fc " + "refs/heads/master\n" + "4f1f932f6ef6d6c9770266775c2db072964d7a64 " + "3fff4bb3172f77b292b0c913749e81bedd3545f5 " + "refs/heads/bolao\n" + ); + assert_non_null(t); + assert_string_equal(t, "3fff4bb3172f77b292b0c913749e81bedd3545fc"); + free(t); +} + + +int +main(void) +{ + const UnitTest tests[] = { + unit_test(test_pre_receive_parse), + }; + return run_tests(tests); +} diff --git a/tests/common/check_stdin.c b/tests/common/check_stdin.c new file mode 100644 index 0000000..c0d222d --- /dev/null +++ b/tests/common/check_stdin.c @@ -0,0 +1,53 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include "../../src/common/stdin.h" + + +int +__wrap_fgetc(FILE *stream) +{ + assert_int_equal(fileno(stream), fileno(stdin)); + return mock_type(int); +} + + +static void +test_read(void **state) +{ + will_return(__wrap_fgetc, EOF); + char *t = bc_stdin_read(); + assert_non_null(t); + assert_string_equal(t, ""); + free(t); + will_return(__wrap_fgetc, 'b'); + will_return(__wrap_fgetc, 'o'); + will_return(__wrap_fgetc, 'l'); + will_return(__wrap_fgetc, 'a'); + will_return(__wrap_fgetc, EOF); + t = bc_stdin_read(); + assert_non_null(t); + assert_string_equal(t, "bola"); + free(t); +} + + +int +main(void) +{ + const UnitTest tests[] = { + unit_test(test_read), + }; + return run_tests(tests); +} -- cgit v1.2.3-18-g5258