diff options
author | kx <kx@radix.pro> | 2023-03-24 03:51:10 +0300 |
---|---|---|
committer | kx <kx@radix.pro> | 2023-03-24 03:51:10 +0300 |
commit | 05d292b208dfe01324826b4c87bbc4da3389a0d5 (patch) | |
tree | b10a2269e9320785f3b61189e75f6778fa167986 /cgitcgi/ui-log.c | |
parent | 40ab18a661ff6ada40e73969be293918d346a2f5 (diff) | |
download | cgit-ui-05d292b208dfe01324826b4c87bbc4da3389a0d5.tar.xz |
Version 0.1.7
Diffstat (limited to 'cgitcgi/ui-log.c')
-rw-r--r-- | cgitcgi/ui-log.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/cgitcgi/ui-log.c b/cgitcgi/ui-log.c new file mode 100644 index 0000000..a768d7b --- /dev/null +++ b/cgitcgi/ui-log.c @@ -0,0 +1,269 @@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <sys/sysinfo.h> +#include <sys/types.h> +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#else +#include <stdint.h> +#endif +#include <stddef.h> /* offsetof(3) */ +#include <dirent.h> +#include <sys/stat.h> /* chmod(2) */ +#include <sys/file.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <limits.h> +#include <string.h> /* strdup(3) */ +#include <libgen.h> /* basename(3) */ +#include <ctype.h> /* tolower(3) */ +#include <errno.h> +#include <time.h> +#include <sys/time.h> +#include <pwd.h> +#include <grp.h> +#include <stdarg.h> +#include <locale.h> +#include <unistd.h> + +#include <git2.h> + +#include <nls.h> + +#include <defs.h> + +#include <fatal.h> +#include <http.h> +#include <html.h> + +#include <dlist.h> +#include <strbuf.h> +#include <repolist.h> +#include <wrapper.h> +#include <system.h> +#include <date.h> + +#include <ctx.h> +#include <git-shared.h> +#include <ui-shared.h> + + +static void print_log_start( struct strbuf *sb ) +{ + if( !sb ) return; + strbuf_addstr( sb, "\n" ); + strbuf_addf( sb, " <div class=\"repo-log-header\">\n" ); + strbuf_addf( sb, " <div class=\"row\">\n" ); + strbuf_addf( sb, " <div class=\"col-date\"><div class=\"log-date\">Date</div></div>\n" ); + strbuf_addf( sb, " <div class=\"col-cmsg\"><div class=\"log-cmsg trunc\">Commit Message</div></div>\n" ); + strbuf_addf( sb, " <div class=\"col-rev\"><div class=\"log-rev trunc\">Rev</div></div>\n" ); + strbuf_addf( sb, " <div class=\"col-author\"><div class=\"log-author trunc\">Author</div></div>\n" ); + strbuf_addf( sb, " </div>\n" ); + strbuf_addf( sb, " </div>\n\n" ); + strbuf_addf( sb, " <div class=\"log\">\n\n" ); +} + +static void print_log_stop( struct strbuf *sb ) +{ + if( !sb ) return; + strbuf_addf( sb, " </div> <!-- End of Log -->\n\n" ); +} + +static void print_direction( struct strbuf *sb, const char *relative_path, int reminder, int limit ) +{ + char *path = NULL; + int page_size = atoi( ctx.vars.page_size ); + int prev, next; + + if( !sb ) return; + + if( relative_path && *relative_path ) + { + path = (char *)xmalloc( strlen( relative_path ) + 2 ); + path[0] = '/'; + sprintf( (char *)&path[1], relative_path ); + } + else + { + path = (char *)xmalloc( 1 ); + path[0] = '\0'; + } + + strbuf_addf( sb, " <div class=\"log-direction\">\n" ); + strbuf_addf( sb, " <div class=\"row\">\n" ); + strbuf_addf( sb, " <div class=\"left col-prev\">\n" ); + strbuf_addf( sb, " <div class=\"prev-log-direction\">\n" ); + + if( ctx.query.ofs ) + { + prev = ctx.query.ofs - page_size; + if( prev < 0 ) prev = 0; + + if( ctx.env.query_string && *ctx.env.query_string ) + strbuf_addf( sb, " <a href=\"/%s%s/?ofs=%d&%s\">≪ Prev</a>\n", ctx.repo.name, path, prev, ctx.env.query_string ); + else + strbuf_addf( sb, " <a href=\"/%s%s/?ofs=%d\">≪ Prev</a>\n", ctx.repo.name, path, prev ); + } + + strbuf_addf( sb, " </div>\n" ); + strbuf_addf( sb, " </div>\n" ); + strbuf_addf( sb, " <div class=\"right col-next\">\n" ); + strbuf_addf( sb, " <div class=\"next-log-direction\">\n" ); + + if( reminder ) + { + next = ctx.query.ofs + page_size; + + if( ctx.env.query_string && *ctx.env.query_string ) + strbuf_addf( sb, " <a href=\"/%s%s/?ofs=%d&%s\">Next ≫</a>\n", ctx.repo.name, path, next, ctx.env.query_string ); + else + strbuf_addf( sb, " <a href=\"/%s%s/?ofs=%d\">Next ≫</a>\n", ctx.repo.name, path, next ); + } + + strbuf_addf( sb, " </div>\n" ); + strbuf_addf( sb, " </div>\n" ); + strbuf_addf( sb, " </div>\n" ); + strbuf_addf( sb, " </div>\n" ); + + free( path ); +} + +static void print_commit_line( struct strbuf *sb, git_commit *commit, const char *relative_path, const char *revision ) +{ + char *path = NULL; + + if( !sb || !commit ) return; + + if( relative_path && *relative_path ) + { + path = (char *)xmalloc( strlen( relative_path ) + 2 ); + path[0] = '/'; + sprintf( (char *)&path[1], relative_path ); + } + else + { + path = (char *)xmalloc( 1 ); + path[0] = '\0'; + } + + { + char id[GIT_OID_HEXSZ+1] = { 0 }; + + const git_oid *oid = git_commit_id( commit ); + const char *message = git_commit_summary( commit ); + git_time_t date = git_commit_time( commit ); + int offset = git_commit_time_offset( commit ); + const git_signature *author = git_commit_author( commit ); + + const char *query_string = ctx_remove_query_param( ctx.env.query_string, "rev" ); + + query_string = ctx_remove_query_param( query_string, "op" ); + + offset = (offset % 60) + ((offset / 60) * 100); + + if( git_oid_fmt( (char *)&id[0], oid ) < 0 || strcmp( (char *)&id[0], revision ) ) return; + + + strbuf_addf( sb, " <div class=\"row\">\n" ); + if( date != -1 ) + { + strbuf_addf( sb, " <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"log-date trunc\">" ); + cgit_print_age( sb, (time_t)date, offset, 0 ); + strbuf_addf( sb, "</div></div>\n" ); + } + else + { + strbuf_addf( sb, " <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"log-date trunc\">unknown</div></div>\n" ); + } + strbuf_addf( sb, " <div class=\"col-cmsg\"><div onclick=\"trunc(this)\" class=\"log-cmsg trunc\">%s</div></div>\n", (char *)message ); + if( query_string && *query_string ) + { + strbuf_addf( sb, " <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"log-rev trunc\"><a title=\"Compare with Previous\" href=\"/%s%s/?op=diff&rev=%s&%s\"><span class=\"rev-short\">%0.8s</span></a></div></div>\n", ctx.repo.name, path, (char *)revision, query_string, (char *)revision ); + } + else + { + strbuf_addf( sb, " <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"log-rev trunc\"><a title=\"Compare with Previous\" href=\"/%s%s/?op=diff&rev=%s\"><span class=\"rev-short\">%0.8s</span></a></div></div>\n", ctx.repo.name, path, (char *)revision, (char *)revision ); + } + strbuf_addf( sb, " <div class=\"col-author\"><div onclick=\"trunc(this)\" class=\"log-author trunc\">%s</div></div>\n", (char *)author->name ); + strbuf_addf( sb, " </div>\n\n" ); + } + + free( path ); +} + + +static void cgit_print_log( struct strbuf *sb, const char *relative_path, const char *revision ) +{ + struct cgit_hex_commits *commits = NULL; + size_t i, limit, reminder, page_size = (size_t)atoi( ctx.vars.page_size ); + + if( !sb ) return; + + print_log_start( sb ); + + cgit_fill_commits_list( &commits, ctx.query.ofs, relative_path, revision ); + + limit = min( page_size, commits->len ); + + for( i = 0; i < limit; ++i ) + { + git_commit *commit = NULL; + commit = lookup_commit_by_hex( commits->hex[i] ); + + print_commit_line( sb, commit, relative_path, (const char *)commits->hex[i] ); + + git_commit_free( commit ); + } + + reminder = commits->len - limit; + + cgit_hex_commits_free( commits ); + + print_log_stop( sb ); + + if( !(!ctx.query.ofs && !reminder) ) + print_direction( sb, relative_path, (int)reminder, (int)limit ); +} + + +void cgit_print_log_page( void ) +{ + FILE *fp; + struct strbuf buf = STRBUF_INIT; + + fp = xfopen( ctx.page.header, "r" ); + (void)strbuf_env_fread( &buf, fp ); + fclose( fp ); + + strbuf_addf( &buf, " <div class=\"content segment\">\n" ); + strbuf_addf( &buf, " <div class=\"container\">\n" ); + strbuf_addf( &buf, " <div class=\"cgit-main-content\">\n" ); + + if( ctx.repo.name ) + { + cgit_print_log( &buf, ctx.repo.relative_path, (!strcmp( ctx.query.rev, "0" )) ? (const char *)&ctx.repo.relative_info.revision[0] : ctx.query.rev ); + } + else + { + strbuf_addf( &buf, " <h1>Requested resource cannot be shown</h1>\n" ); + strbuf_addf( &buf, " <p class='leading'>Repository '%s' not found.</p>\n", ctx.repo.name ); + } + + strbuf_addf( &buf, " </div> <!-- End of cgit-main-content -->\n" ); + strbuf_addf( &buf, " </div> <!-- End of container -->\n" ); + strbuf_addf( &buf, " </div> <!-- End of content segment -->\n" ); + + fp = xfopen( ctx.page.footer, "r" ); + (void)strbuf_env_fread( &buf, fp ); + fclose( fp ); + + ctx.page.size = buf.len; + cgit_print_http_headers(); + strbuf_write( &buf, STDOUT_FILENO ); + strbuf_release( &buf ); +} |