mobley

C Git HTTP server
Log | Files | Refs | Submodules | README | git clone https://git.ne02ptzero.me/git/mobley

commit 66eba8eeb39bad68ffebb509b17a13193c54efb4
parent a75ab7b28d7889dae84b63f674e41f98233e832d
Author: Louis Solofrizzo <lsolofrizzo@online.net>
Date:   Sat,  5 Jan 2019 21:49:57 +0100

Add working tree preview by OID and branch:

The tree listing is now working with a specific oid or branch in the
URL. File display and static serving are working too.

Signed-off-by: Louis Solofrizzo <lsolofrizzo@online.net>

Diffstat:
Mdiff.c | 12+++++++++---
Mfile.c | 2+-
Mhtml.c | 44++++++++++++++++++++++++++++++++++++++++++--
Mhtml.h | 1+
Mrepository.c | 17++++++++++++++---
Mrepository.h | 1+
Mrepository_handler.c | 12+++++++-----
Mrepository_log.c | 1+
Mserver.c | 8++++++++
Mserver.h | 1+
Mstatic.c | 2+-
Mstyle/main.css | 4++++
12 files changed, 90 insertions(+), 15 deletions(-)

diff --git a/diff.c b/diff.c @@ -115,7 +115,14 @@ static void diff_print_file(mobley_t *ctx, server_req_t *r, char *begin, char *e if (data) { - html_raw("<b>%s</b><hr>", files[1]); + html_open("b") { + html("a", files[1], + .href = __format("tree/%s", files[1]), + .oid = r->commit_oid, + .class = "diff-file-link" + ); + } html_close("b"); + html_nd("hr"); diff_print_diff_regions(ctx, r, files[1], data); } free(org); @@ -140,9 +147,8 @@ static bool diff_print_patch(mobley_t *ctx, server_req_t *r, git_buf *buf) if (strncmp(line, DIFF_BEGIN, sizeof(DIFF_BEGIN) - 1) == 0) { if (diff_line != NULL) - { diff_print_file(ctx, r, diff_line, line); - } + diff_line = line; } diff --git a/file.c b/file.c @@ -122,7 +122,7 @@ bool _file_show_hl_code(mobley_t *ctx, server_req_t *r, const char *path, const for (int i = 0; i < args->start_line; i++) write(fd_in, "\n", 1); - write(fd_in, blob, size); + write(fd_in, blob, size - 1); close(fd_in); source_highlight_file(__path_in, __path_out); diff --git a/html.c b/html.c @@ -18,6 +18,7 @@ void _html(server_req_t *r, const mobley_t *ctx, const char *b, const char *d, html_args_t *a) { + bool add_param = false; evbuffer_add_printf(r->req->buffer_out, "<%s", b); if (a->href != NULL) @@ -30,7 +31,8 @@ void _html(server_req_t *r, const mobley_t *ctx, const char *b, const char *d, else if (a->href[0] == '/') { evbuffer_add_printf(r->req->buffer_out, - " href=\"http://%s:%d%s\"", ctx->ip, ctx->port, a->href); + " href=\"http://%s:%d%s", ctx->ip, ctx->port, a->href); + add_param = true; } else if (strncmp(a->href, "http", sizeof("http") - 1) == 0 || a->href[0] == '#') { @@ -39,8 +41,46 @@ void _html(server_req_t *r, const mobley_t *ctx, const char *b, const char *d, else { evbuffer_add_printf(r->req->buffer_out, - " href=\"http://%s:%d/%s/%s\"", ctx->ip, ctx->port, + " href=\"http://%s:%d/%s/%s", ctx->ip, ctx->port, (r->route == NULL ? "" : r->route), a->href); + add_param = true; + } + + if (add_param) + { + bool is_first = true; + static const char *params[] = { + "oid", + "branch" + }; + + + STATIC_ARRAY_FOREACH(const char **val, params) + { + if (strcmp(*val, "oid") == 0 && a->oid != NULL) + continue; + + const char *qry = evhtp_kv_find(r->req->uri->query, *val); + if (qry != NULL) + { + if (is_first) + { + evbuffer_add_printf(r->req->buffer_out, "?"); + is_first = false; + evbuffer_add_printf(r->req->buffer_out, "%s=%s", *val, qry); + } + else + evbuffer_add_printf(r->req->buffer_out, "&%s=%s", *val, qry); + } + } + if (a->oid != NULL) + { + if (is_first) + evbuffer_add_printf(r->req->buffer_out, "?oid=%s", a->oid); + else + evbuffer_add_printf(r->req->buffer_out, "&oid=%s", a->oid); + } + evbuffer_add_printf(r->req->buffer_out, "\""); } } if (a->class != NULL) diff --git a/html.h b/html.h @@ -34,6 +34,7 @@ typedef struct { const char *align; const char *colspan; const char *width; + const char *oid; bool closing_slash; bool is_static; } html_args_t; diff --git a/repository.c b/repository.c @@ -14,6 +14,7 @@ */ #include <repository.h> +#include <server.h> git_commit *repository_get_last_commit_from_default(repository_t *repo) { @@ -24,17 +25,27 @@ git_commit *repository_get_last_commit_from_default(repository_t *repo) git_commit *repository_get_last_commit(repository_t *repo, const char *ref) { git_commit *ret = NULL; - git_oid oid_parent_commit/* = { 0 }*/; + git_oid oid_parent_commit; char branch[1024] = { 0 }; if (repo->repo == NULL) return NULL; - snprintf(branch, sizeof(branch), "refs/heads/%s", ref); + if (ref == NULL) + return repository_get_last_commit_from_default(repo); - if (git_reference_name_to_id(&oid_parent_commit, repo->repo, branch) == 0) + if (git_oid_fromstr(&oid_parent_commit, ref) == 0) + { if (git_commit_lookup(&ret, repo->repo, &oid_parent_commit) == 0) return ret; + } + else + { + snprintf(branch, sizeof(branch), "refs/heads/%s", ref); + if (git_reference_name_to_id(&oid_parent_commit, repo->repo, branch) == 0) + if (git_commit_lookup(&ret, repo->repo, &oid_parent_commit) == 0) + return ret; + } return NULL; } diff --git a/repository.h b/repository.h @@ -109,6 +109,7 @@ static inline bool path_commit_add_node(list_head_t *head, const char *path) } bool repository_get_log_from_paths(repository_t *repo, const git_oid *oid, const char *path, list_head_t *paths, size_t max); + bool repository_get_log_from_path_ref(repository_t *repo, const char *path, const char *ref, list_head_t *out); bool repository_get_log_from_path_default(repository_t *repo, const char *path, list_head_t *out); diff --git a/repository_handler.c b/repository_handler.c @@ -306,11 +306,13 @@ end: bool repository_route_handler(mobley_t *ctx, server_req_t *r) { - if (r->repo->default_branch == NULL) - r->branch = "master"; - else - r->branch = r->repo->default_branch; - /* Branch from URL */ + if (r->branch == NULL) + { + if (r->repo->default_branch == NULL) + r->branch = "master"; + else + r->branch = r->repo->default_branch; + } /* Index */ if (r->uri.next == &r->uri) diff --git a/repository_log.c b/repository_log.c @@ -254,6 +254,7 @@ bool repository_log_commit(mobley_t *ctx, server_req_t *r, const char *sha) git_oid oid; bool ret = false; + r->commit_oid = sha; git_oid_fromstr(&oid, sha); git_commit_lookup(&one, r->repo->repo, &oid); if (one == NULL) diff --git a/server.c b/server.c @@ -42,6 +42,14 @@ static bool server_route_request(server_req_t *r, mobley_t *ctx) bool ret = false; repository_t *repo; + const char *oid = evhtp_kv_find(r->req->uri->query, "oid"); + const char *branch = evhtp_kv_find(r->req->uri->query, "branch"); + + if (oid != NULL) + r->branch = (char *)oid; + else if (branch != NULL) + r->branch = (char *)branch; + if (first->val == NULL) { server_req_set_content_type(r, "text/html; charset=iso-8859-1"); diff --git a/server.h b/server.h @@ -33,6 +33,7 @@ typedef struct { repository_t *repo; char *path; char *branch; + const char *commit_oid; void *ctx; list_head_t items; } server_req_t; diff --git a/static.c b/static.c @@ -68,7 +68,7 @@ static bool static_send_repo_file(const mobley_t *ctx, server_req_t *r, const ch if (iter == NULL) return false; - head = repository_get_last_commit(iter, "master"); + head = repository_get_last_commit(iter, r->branch); if (head == NULL) goto end; diff --git a/style/main.css b/style/main.css @@ -358,3 +358,7 @@ table tbody .commit a { position: absolute; width: 96.5%; } + +.diff-file-link { + color: #999; +}