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-diff.c | |
parent | 40ab18a661ff6ada40e73969be293918d346a2f5 (diff) | |
download | cgit-ui-05d292b208dfe01324826b4c87bbc4da3389a0d5.tar.xz |
Version 0.1.7
Diffstat (limited to 'cgitcgi/ui-diff.c')
-rw-r--r-- | cgitcgi/ui-diff.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/cgitcgi/ui-diff.c b/cgitcgi/ui-diff.c new file mode 100644 index 0000000..457407c --- /dev/null +++ b/cgitcgi/ui-diff.c @@ -0,0 +1,201 @@ + +#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_commit( struct strbuf *sb, git_commit *commit, const char *revision, const char *parent, int files, int insertions, int deletions ) +{ + const git_oid *oid; + const char *message; + git_time_t date; + int offset; + const git_signature *author; + const git_signature *committer; + + char id[GIT_OID_HEXSZ+1] = { 0 }; + + struct strbuf fbuf = STRBUF_INIT; + struct strbuf ibuf = STRBUF_INIT; + struct strbuf dbuf = STRBUF_INIT; + + struct strbuf atime = STRBUF_INIT; + struct strbuf ctime = STRBUF_INIT; + struct strbuf cmsg = STRBUF_INIT; + + char *raw = NULL; + + if( !sb || !commit || !revision || !parent ) return; + + oid = git_commit_id( commit ); + if( git_oid_fmt( (char *)&id[0], oid ) < 0 || strcmp( (char *)&id[0], revision ) ) return; + + message = git_commit_summary( commit ); + author = git_commit_author( commit ); + committer = git_commit_committer( commit ); + + strbuf_addf( &cmsg, "%s", message ); + raw = strbuf_detach( &cmsg, NULL ); + strbuf_addstr_xml_quoted( &cmsg, (const char *)raw ); + free( raw ); + + strbuf_addstr( sb, " <div class=\"diff-cmsg\">\n" ); + strbuf_addstr( sb, " <div class=\"cmsg-commit\">\n" ); + + date = author->when.time; + offset = author->when.offset; + offset = (offset % 60) + ((offset / 60) * 100); + show_date( &atime, (time_t)date, offset, cgit_date_mode( DATE_ISO8601 ) ); + + strbuf_addf( sb, "<span class=\"head\"> author:</span> %s <%s> %s\n", author->name, author->email, (char *)&atime.buf[0] ); + strbuf_release( &atime ); + + date = committer->when.time; + offset = committer->when.offset; + offset = (offset % 60) + ((offset / 60) * 100); + show_date( &ctime, (time_t)date, offset, cgit_date_mode( DATE_ISO8601 ) ); + + strbuf_addf( sb, "<span class=\"head\">committer:</span> %s <%s> %s\n", committer->name, committer->email, (char *)&ctime.buf[0] ); + strbuf_release( &ctime ); + + strbuf_addf( sb, "<span class=\"head\"> commit:</span> <span class=\"revision\">%s</span>\n", revision ); + strbuf_addf( sb, "<span class=\"head\"> parent:</span> <span class=\"parent\">%s</span>\n", parent ); + strbuf_addstr( sb, " </div>\n" ); + strbuf_addstr( sb, " <div class=\"cmsg-summary\">\n" ); + strbuf_addstr( sb, " <div class=\"head\">\n" ); + strbuf_addstr( sb, " Commit Summary:\n" ); + strbuf_addstr( sb, " </div>\n" ); + strbuf_addf( sb, " <div class=\"message\">%s</div>\n", (char *)&cmsg.buf[0] ); + strbuf_release( &cmsg ); + strbuf_addstr( sb, " </div>\n" ); + strbuf_addstr( sb, " </div>\n" ); + + strbuf_addf( &fbuf, Q_("%d file changed", "%d files changed", files), files ); + strbuf_addf( &ibuf, Q_("%d insertion", "%d insertions", insertions), insertions ); + strbuf_addf( &dbuf, Q_("%d deletion", "%d deletions", deletions), deletions ); + + strbuf_addstr( sb, " <div class=\"diff-stat\">\n" ); + strbuf_addstr( sb, " <div class=\"head\">Diffstat:</div>\n" ); + strbuf_addf( sb, " <div class=\"line\">%s, %s, %s</div>\n", (char *)&fbuf.buf[0], (char *)&ibuf.buf[0], (char *)&dbuf.buf[0] ); + strbuf_addstr( sb, " </div>\n" ); + + strbuf_release( &fbuf ); + strbuf_release( &ibuf ); + strbuf_release( &dbuf ); +} + +static void cgit_print_diff( struct strbuf *sb, const char *relative_path, const char *revision ) +{ + struct strbuf buf = STRBUF_INIT; + + git_commit *commit = NULL; + char parent_hex[GIT_OID_HEXSZ+1] = { 0 }; + int files, insertions, deletions; + char *raw = NULL; + + if( !sb ) return; + + commit = lookup_commit_by_hex( revision ); + + cgit_diff_with_parent( &buf, (char *)&parent_hex[0], GIT_OID_HEXSZ+1, &files, &insertions, &deletions, revision, ( relative_path && *relative_path ) ? relative_path : "/" ); + + print_commit( sb, commit, revision, (const char *)&parent_hex[0], files, insertions, deletions ); + git_commit_free( commit ); + + strbuf_addf( sb, "<pre><code class='language-Diff'>" ); + + raw = strbuf_detach( &buf, NULL ); + strbuf_addstr_xml_quoted( &buf, (const char *)raw ); + free( raw ); + + strbuf_addbuf( sb, (const struct strbuf *)&buf ); + strbuf_release( &buf ); + + strbuf_addstr( sb, "\n</code></pre>\n" ); +} + +void cgit_print_diff_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_diff( &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 ); +} |