#ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef HAVE_INTTYPES_H #include #else #include #endif #include /* offsetof(3) */ #include #include /* chmod(2) */ #include #include #include #include #include /* strdup(3) */ #include /* basename(3) */ #include /* tolower(3) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void print_log_start( struct strbuf *sb ) { if( !sb ) return; strbuf_addstr( sb, "\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
Date
\n" ); strbuf_addf( sb, "
Commit Message
\n" ); strbuf_addf( sb, "
Rev
\n" ); strbuf_addf( sb, "
Author
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n\n" ); strbuf_addf( sb, "
\n\n" ); } static void print_log_stop( struct strbuf *sb ) { if( !sb ) return; strbuf_addf( sb, "
\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, "
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\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, " ≪  Prev\n", ctx.repo.name, path, prev, ctx.env.query_string ); else strbuf_addf( sb, " ≪  Prev\n", ctx.repo.name, path, prev ); } strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); if( reminder ) { next = ctx.query.ofs + page_size; if( ctx.env.query_string && *ctx.env.query_string ) strbuf_addf( sb, " Next  ≫\n", ctx.repo.name, path, next, ctx.env.query_string ); else strbuf_addf( sb, " Next  ≫\n", ctx.repo.name, path, next ); } strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\n" ); strbuf_addf( sb, "
\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, "
\n" ); if( date != -1 ) { strbuf_addf( sb, "
" ); cgit_print_age( sb, (time_t)date, offset, 0 ); strbuf_addf( sb, "
\n" ); } else { strbuf_addf( sb, "
unknown
\n" ); } strbuf_addf( sb, "
%s
\n", (char *)message ); if( query_string && *query_string ) { strbuf_addf( sb, " \n", ctx.repo.name, path, (char *)revision, query_string, (char *)revision ); } else { strbuf_addf( sb, " \n", ctx.repo.name, path, (char *)revision, (char *)revision ); } strbuf_addf( sb, "
%s
\n", (char *)author->name ); strbuf_addf( sb, "
\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, "
\n" ); strbuf_addf( &buf, "
\n" ); strbuf_addf( &buf, "
\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, "

Requested resource cannot be shown

\n" ); strbuf_addf( &buf, "

Repository '%s' not found.

\n", ctx.repo.name ); } strbuf_addf( &buf, "
\n" ); strbuf_addf( &buf, "
\n" ); strbuf_addf( &buf, "
\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 ); }