{! /* * Copyright (c) 2022 Omar Polo * Copyright (c) 2016, 2019, 2020-2022 Tracey Emery * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include "got_object.h" #include "proc.h" #include "gotwebd.h" #include "tmpl.h" static int gotweb_render_blob_line(struct template *, const char *, size_t); static int gotweb_render_tree_item(struct template *, struct got_tree_entry *); static inline int rss_tag_item(struct template *, struct repo_tag *); static inline int rss_author(struct template *, char *); static int gotweb_render_age(struct template *tp, time_t time, int ref_tm) { const struct got_error *err; char *age; int r; err = gotweb_get_time_str(&age, time, ref_tm); if (err) return 0; r = tp->tp_puts(tp, age); free(age); return r; } !} {{ define gotweb_render_header(struct template *tp) }} {! struct request *c = tp->tp_arg; struct server *srv = c->srv; struct querystring *qs = c->t->qs; struct gotweb_url u_path; const char *prfx = c->document_uri; const char *css = srv->custom_css; memset(&u_path, 0, sizeof(u_path)); u_path.index_page = -1; u_path.page = -1; u_path.action = SUMMARY; !} {{ srv->site_name }}
{{ end }} {{ define gotweb_render_footer(struct template *tp) }} {! struct request *c = tp->tp_arg; struct server *srv = c->srv; !}
{{ if srv->show_site_owner }} {{ srv->site_owner }} {{ end }}
{{ end }} {{ define gotweb_render_repo_table_hdr(struct template *tp) }} {! struct request *c = tp->tp_arg; struct server *srv = c->srv; !}
Project
{{ if srv->show_repo_description }}
Description
{{ end }} {{ if srv->show_repo_owner }}
Owner
{{ end }} {{ if srv->show_repo_age }}
Last Change
{{ end }}
{{ end }} {{ define gotweb_render_repo_fragment(struct template *tp, struct repo_dir *repo_dir) }} {! struct request *c = tp->tp_arg; struct server *srv = c->srv; struct gotweb_url summary = { .action = SUMMARY, .index_page = -1, .page = -1, .path = repo_dir->name, }, briefs = { .action = BRIEFS, .index_page = -1, .page = -1, .path = repo_dir->name, }, commits = { .action = COMMITS, .index_page = -1, .page = -1, .path = repo_dir->name, }, tags = { .action = TAGS, .index_page = -1, .page = -1, .path = repo_dir->name, }, tree = { .action = TREE, .index_page = -1, .page = -1, .path = repo_dir->name, }, rss = { .action = RSS, .index_page = -1, .page = -1, .path = repo_dir->name, }; !}
{{ if srv->show_repo_description }}
{{ repo_dir->description }}
{{ end }} {{ if srv->show_repo_owner }}
{{ repo_dir->owner }}
{{ end }} {{ if srv->show_repo_age }}
{{ repo_dir->age }}
{{ end }}
{{ end }} {{ define gotweb_render_briefs(struct template *tp) }} {! const struct got_error *error; struct request *c = tp->tp_arg; struct server *srv = c->srv; struct transport *t = c->t; struct querystring *qs = c->t->qs; struct repo_commit *rc; struct repo_dir *repo_dir = t->repo_dir; struct gotweb_url diff_url, tree_url; char *tmp; diff_url = (struct gotweb_url){ .action = DIFF, .index_page = -1, .page = -1, .path = repo_dir->name, .headref = qs->headref, }; tree_url = (struct gotweb_url){ .action = TREE, .index_page = -1, .page = -1, .path = repo_dir->name, .headref = qs->headref, }; if (qs->action == SUMMARY) { qs->action = BRIEFS; error = got_get_repo_commits(c, D_MAXSLCOMMDISP); } else error = got_get_repo_commits(c, srv->max_commits_display); if (error) return -1; !}
Commit Briefs
{{ tailq-foreach rc &t->repo_commits entry }} {! diff_url.commit = rc->commit_id; tree_url.commit = rc->commit_id; tmp = strchr(rc->author, '<'); if (tmp) *tmp = '\0'; tmp = strchr(rc->commit_msg, '\n'); if (tmp) *tmp = '\0'; !}
{{ render gotweb_render_age(tp, rc->committer_time, TM_DIFF) }}
{{ rc->author }}
{{ rc->commit_msg }} {{ if rc->refs_str }} {{ " " }} ({{ rc->refs_str }}) {{ end }}
{{ end }} {{ if t->next_id || t->prev_id }} {{ render gotweb_render_navs(tp) }} {{ end }}
{{ end }} {{ define gotweb_render_navs(struct template *tp) }} {! struct request *c = tp->tp_arg; struct transport *t = c->t; struct gotweb_url prev, next; int have_prev, have_next; gotweb_get_navs(c, &prev, &have_prev, &next, &have_next); !}
{{ finally }} {! free(t->next_id); t->next_id = NULL; free(t->prev_id); t->prev_id = NULL; !} {{ end }} {{ define gotweb_render_commits(struct template *tp) }} {! struct request *c = tp->tp_arg; struct transport *t = c->t; struct repo_dir *repo_dir = t->repo_dir; struct repo_commit *rc; struct gotweb_url diff, tree; diff = (struct gotweb_url){ .action = DIFF, .index_page = -1, .page = -1, .path = repo_dir->name, }; tree = (struct gotweb_url){ .action = TREE, .index_page = -1, .page = -1, .path = repo_dir->name, }; !}
Commits
{{ tailq-foreach rc &t->repo_commits entry }} {! diff.commit = rc->commit_id; tree.commit = rc->commit_id; !}
Commit:
{{ rc->commit_id }}
Author:
{{ rc->author }}
Date:
{{ render gotweb_render_age(tp, rc->committer_time, TM_LONG) }}
{{ "\n" }} {{ rc->commit_msg }}
{{ end }} {{ if t->next_id || t->prev_id }} {{ render gotweb_render_navs(tp) }} {{ end }}
{{ end }} {{ define gotweb_render_blob(struct template *tp, struct got_blob_object *blob) }} {! struct request *c = tp->tp_arg; struct transport *t = c->t; struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits); !}
Blob
Date:
{{ render gotweb_render_age(tp, rc->committer_time, TM_LONG) }}
Message:
{{ rc->commit_msg }}
      {{ render got_output_blob_by_lines(tp, blob, gotweb_render_blob_line) }}
    
{{ end }} {{ define gotweb_render_blob_line(struct template *tp, const char *line, size_t no) }} {! char lineno[16]; int r; r = snprintf(lineno, sizeof(lineno), "%zu", no); if (r < 0 || (size_t)r >= sizeof(lineno)) return -1; !}
{{ line }}
{{ end }} {{ define gotweb_render_tree(struct template *tp) }} {! struct request *c = tp->tp_arg; struct transport *t = c->t; struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits); !}
Tree
Tree:
{{ rc->tree_id }}
Date:
{{ render gotweb_render_age(tp, rc->committer_time, TM_LONG) }}
Message:
{{ rc->commit_msg }}
{{ render got_output_repo_tree(c, gotweb_render_tree_item) }}
{{ end }} {{ define gotweb_render_tree_item(struct template *tp, struct got_tree_entry *te) }} {! struct request *c = tp->tp_arg; struct transport *t = c->t; struct querystring *qs = t->qs; struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits); const char *modestr = ""; const char *name; const char *folder; char *dir = NULL; mode_t mode; struct gotweb_url url = { .index_page = -1, .page = -1, .commit = rc->commit_id, .path = qs->path, }; name = got_tree_entry_get_name(te); mode = got_tree_entry_get_mode(te); folder = qs->folder ? qs->folder : ""; if (S_ISDIR(mode)) { if (asprintf(&dir, "%s/%s", folder, name) == -1) return (-1); url.action = TREE; url.folder = dir; } else { url.action = BLOB; url.folder = folder; url.file = name; } if (got_object_tree_entry_is_submodule(te)) modestr = "$"; else if (S_ISLNK(mode)) modestr = "@"; else if (S_ISDIR(mode)) modestr = "/"; else if (mode & S_IXUSR) modestr = "*"; !}
{{ if S_ISDIR(mode) }}
 
{{ else }}
{! url.action = COMMITS; !} commits {{ " | " }} {! url.action = BLAME; !} blame
{{ end }}
{{ finally }} {! free(dir); !} {{ end }} {{ define gotweb_render_rss(struct template *tp) }} {! struct request *c = tp->tp_arg; struct server *srv = c->srv; struct transport *t = c->t; struct repo_dir *repo_dir = t->repo_dir; struct repo_tag *rt; struct gotweb_url summary = { .action = SUMMARY, .index_page = -1, .page = -1, .path = repo_dir->name, }; !} Tags of {{ repo_dir->name }} {{ if srv->show_repo_description }} {{ repo_dir->description }} {{ end }} {{ tailq-foreach rt &t->repo_tags entry }} {{ render rss_tag_item(tp, rt) }} {{ end }} {{ end }} {{ define rss_tag_item(struct template *tp, struct repo_tag *rt) }} {! struct request *c = tp->tp_arg; struct transport *t = c->t; struct repo_dir *repo_dir = t->repo_dir; char *tag_name = rt->tag_name; struct gotweb_url tag = { .action = TAG, .index_page = -1, .page = -1, .path = repo_dir->name, .commit = rt->commit_id, }; if (strncmp(tag_name, "refs/tags/", 10) == 0) tag_name += 10; !} {{ repo_dir->name }} {{" "}} {{ tag_name }} {{ rt->tag_commit }}]]> {{ render rss_author(tp, rt->tagger) }} {{ rt->commit_id }} {{ render gotweb_render_age(tp, rt->tagger_time, TM_RFC822) }} {{ end }} {{ define rss_author(struct template *tp, char *author) }} {! char *t, *mail; /* what to do if the author name contains a paren? */ if (strchr(author, '(') != NULL || strchr(author, ')') != NULL) return 0; t = strchr(author, '<'); if (t == NULL) return 0; *t = '\0'; mail = t+1; while (isspace((unsigned char)*--t)) *t = '\0'; t = strchr(mail, '>'); if (t == NULL) return 0; *t = '\0'; !} {{ mail }} {{" "}} ({{ author }}) {{ end }}