cGit-UI for Git Repositories

cGit-UI – is a web interface for Git Repositories. cGit CGI script is writen in C and therefore it's fast enough

3 Commits   0 Branches   1 Tag
05d292b2 (kx 2023-03-24 03:51:10 +0300   1) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   2) #ifdef HAVE_CONFIG_H
05d292b2 (kx 2023-03-24 03:51:10 +0300   3) #include <config.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   4) #endif
05d292b2 (kx 2023-03-24 03:51:10 +0300   5) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   6) #include <stdlib.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   7) #include <stdio.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   8) #include <sys/sysinfo.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   9) #include <sys/types.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  10) #ifdef HAVE_INTTYPES_H
05d292b2 (kx 2023-03-24 03:51:10 +0300  11) #include <inttypes.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  12) #else
05d292b2 (kx 2023-03-24 03:51:10 +0300  13) #include <stdint.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  14) #endif
05d292b2 (kx 2023-03-24 03:51:10 +0300  15) #include <stddef.h>   /* offsetof(3) */
05d292b2 (kx 2023-03-24 03:51:10 +0300  16) #include <dirent.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  17) #include <sys/stat.h> /* chmod(2)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300  18) #include <sys/file.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  19) #include <sys/mman.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  20) #include <fcntl.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  21) #include <limits.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  22) #include <string.h>   /* strdup(3)   */
05d292b2 (kx 2023-03-24 03:51:10 +0300  23) #include <libgen.h>   /* basename(3) */
05d292b2 (kx 2023-03-24 03:51:10 +0300  24) #include <ctype.h>    /* tolower(3)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300  25) #include <errno.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  26) #include <time.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  27) #include <sys/time.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  28) #include <pwd.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  29) #include <grp.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  30) #include <stdarg.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  31) #include <locale.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  32) #include <math.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  33) #include <unistd.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  34) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  35) #include <git2.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  36) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  37) #include <nls.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  38) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  39) #include <defs.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  40) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  41) #include <fatal.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  42) #include <http.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  43) #include <html.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  44) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  45) #include <dlist.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  46) #include <strbuf.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  47) #include <repolist.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  48) #include <wrapper.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  49) #include <system.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  50) #include <date.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  51) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  52) #include <ctx.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  53) #include <git-shared.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  54) #include <ui-shared.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  55) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  56) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  57) void cgit_change_location( const char *location )
05d292b2 (kx 2023-03-24 03:51:10 +0300  58) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  59)   if( ctx.env.no_http && !strcmp( ctx.env.no_http, "1" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  60)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  61) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  62)   htmlf( "Status: %d %s\n", 302, "Found" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  63)   htmlf( "Location: %s\n", location );
05d292b2 (kx 2023-03-24 03:51:10 +0300  64)   html( "\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  65) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  66)   exit( 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300  67) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  68) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  69) void cgit_print_http_headers( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  70) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  71)   if( ctx.env.no_http && !strcmp( ctx.env.no_http, "1" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  72)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  73) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  74)   /*****************************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300  75)     If we pass 'Status: 200 OK' header then nginx+uWsgi
05d292b2 (kx 2023-03-24 03:51:10 +0300  76)     will duplicate other headers randomly 
05d292b2 (kx 2023-03-24 03:51:10 +0300  77)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300  78)   if( ctx.page.status != 200 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  79)     htmlf( "Status: %d %s\n", ctx.page.status, ctx.page.status_message );
05d292b2 (kx 2023-03-24 03:51:10 +0300  80) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  81)   if( ctx.page.mimetype && ctx.page.charset )
05d292b2 (kx 2023-03-24 03:51:10 +0300  82)     htmlf( "Content-Type: %s; charset=%s\n", ctx.page.mimetype, ctx.page.charset );
05d292b2 (kx 2023-03-24 03:51:10 +0300  83)   else if( ctx.page.mimetype )
05d292b2 (kx 2023-03-24 03:51:10 +0300  84)     htmlf( "Content-Type: %s\n", ctx.page.mimetype );
05d292b2 (kx 2023-03-24 03:51:10 +0300  85) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  86)   if( ctx.page.size )
05d292b2 (kx 2023-03-24 03:51:10 +0300  87)     htmlf( "Content-Length: %zd\n", ctx.page.size );
05d292b2 (kx 2023-03-24 03:51:10 +0300  88) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  89)   if( !ctx.env.authenticated )
05d292b2 (kx 2023-03-24 03:51:10 +0300  90)     html( "Cache-Control: no-cache, no-store\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  91) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  92)   htmlf( "Last-Modified: %s\n", http_date( ctx.page.modified ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  93)   htmlf( "Expires: %s\n", http_date( ctx.page.expires ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  94) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  95)   html( "\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  96) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  97) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  98) const struct date_mode *cgit_date_mode( enum date_mode_type type )
05d292b2 (kx 2023-03-24 03:51:10 +0300  99) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 100)   static struct date_mode mode;
05d292b2 (kx 2023-03-24 03:51:10 +0300 101)   mode.type = type;
05d292b2 (kx 2023-03-24 03:51:10 +0300 102)   mode.local = 0; /* may be from ctx.cfg.local_time; =0/1 */
05d292b2 (kx 2023-03-24 03:51:10 +0300 103)   return &mode;
05d292b2 (kx 2023-03-24 03:51:10 +0300 104) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 105) /* OR data_mode_from_type():
05d292b2 (kx 2023-03-24 03:51:10 +0300 106)    struct date_mode *mode = DATE_MODE( DATE_ISO8601 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 107)    but in this case mode.local is always zero!
05d292b2 (kx 2023-03-24 03:51:10 +0300 108)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300 109) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 110) static void print_rel_date( struct strbuf *sb, time_t t, int tz,
05d292b2 (kx 2023-03-24 03:51:10 +0300 111)                             const char *class, const char *value )
05d292b2 (kx 2023-03-24 03:51:10 +0300 112) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 113)   if( !sb || !t ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 114) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 115)   strbuf_addf( sb, "<span class='%s' title='", class );
05d292b2 (kx 2023-03-24 03:51:10 +0300 116)   show_date( sb, t, tz, cgit_date_mode( DATE_ISO8601 ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 117)   strbuf_addf( sb, "'>%s</span>", value );
05d292b2 (kx 2023-03-24 03:51:10 +0300 118) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 119) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 120) void cgit_print_age( struct strbuf *sb, time_t t, int tz, time_t max_relative )
05d292b2 (kx 2023-03-24 03:51:10 +0300 121) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 122)   time_t now, secs;
05d292b2 (kx 2023-03-24 03:51:10 +0300 123)   char buf[32] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 124)   size_t val;
05d292b2 (kx 2023-03-24 03:51:10 +0300 125) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 126)   if( !sb || !t ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 127) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 128)   now = time( NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 129)   secs = now - t;
05d292b2 (kx 2023-03-24 03:51:10 +0300 130)   if( secs < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 131)     secs = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 132) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 133)   if( secs > max_relative && max_relative >= 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 134)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 135) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 136)     strbuf_addstr( sb, "<span title='" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 137)     show_date( sb, t, tz, cgit_date_mode( DATE_ISO8601 ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 138)     strbuf_addstr( sb, "'>" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 139)     show_date( sb, t, tz, cgit_date_mode( DATE_SHORT ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 140)     strbuf_addstr( sb, "</span>" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 141)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 142)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 143) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 144)   if( secs < TM_HOUR * 2 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 145)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 146)     val = (size_t)round(secs * 1.0 / TM_MIN);
05d292b2 (kx 2023-03-24 03:51:10 +0300 147)     snprintf( (char *)&buf[0], 32, Q_("%"PRIdMAX" minute", "%"PRIdMAX" minutes", val), val );
05d292b2 (kx 2023-03-24 03:51:10 +0300 148)     print_rel_date( sb, t, tz, "age-mins", (const char *)&buf[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 149)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 150)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 151)   if( secs < TM_DAY * 2 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 152)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 153)     val = (size_t)round(secs * 1.0 / TM_HOUR);
05d292b2 (kx 2023-03-24 03:51:10 +0300 154)     snprintf( (char *)&buf[0], 32, Q_("%"PRIdMAX" hour", "%"PRIdMAX" hours", val), val );
05d292b2 (kx 2023-03-24 03:51:10 +0300 155)     print_rel_date( sb, t, tz, "age-hours", (const char *)&buf[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 156)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 157)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 158)   if( secs < TM_WEEK * 2 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 159)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 160)     val = (size_t)round(secs * 1.0 / TM_DAY);
05d292b2 (kx 2023-03-24 03:51:10 +0300 161)     snprintf( (char *)&buf[0], 32, Q_("%"PRIdMAX" day", "%"PRIdMAX" days", val), val );
05d292b2 (kx 2023-03-24 03:51:10 +0300 162)     print_rel_date( sb, t, tz, "age-days", (const char *)&buf[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 163)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 164)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 165)   if( secs < TM_MONTH * 2 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 166)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 167)     val = (size_t)round(secs * 1.0 / TM_WEEK);
05d292b2 (kx 2023-03-24 03:51:10 +0300 168)     snprintf( (char *)&buf[0], 32, Q_("%"PRIdMAX" week", "%"PRIdMAX" weeks", val), val );
05d292b2 (kx 2023-03-24 03:51:10 +0300 169)     print_rel_date( sb, t, tz, "age-weeks", (const char *)&buf[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 170)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 171)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 172)   if( secs < TM_YEAR * 2 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 173)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 174)     val = (size_t)round(secs * 1.0 / TM_MONTH);
05d292b2 (kx 2023-03-24 03:51:10 +0300 175)     snprintf( (char *)&buf[0], 32, Q_("%"PRIdMAX" month", "%"PRIdMAX" months", val), val );
05d292b2 (kx 2023-03-24 03:51:10 +0300 176)     print_rel_date( sb, t, tz, "age-months", (const char *)&buf[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 177)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 178)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 179) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 180)   val = (size_t)round(secs * 1.0 / TM_YEAR);
05d292b2 (kx 2023-03-24 03:51:10 +0300 181)   snprintf( (char *)&buf[0], 32, Q_("%"PRIdMAX" year", "%"PRIdMAX" years", val), val );
05d292b2 (kx 2023-03-24 03:51:10 +0300 182)   print_rel_date( sb, t, tz, "age-years", (const char *)&buf[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 183) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 184) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 185) void cgit_search_repo( const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 186) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 187)   struct repo *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 188) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 189)   if( !path || !*path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 190) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 191)   repo = lookup_repo( config, path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 192)   if( repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300 193)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 194)     int position = repo_position( config, repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 195)     if( position != -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 196)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 197)       char location[1024] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 198) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 199)       sprintf( (char *)&location[0], "/?ofs=%d", position );
05d292b2 (kx 2023-03-24 03:51:10 +0300 200)       cgit_change_location( (const char *)&location[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 201)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 202)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 203) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 204) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 205) void cgit_repo_info( struct cgit_info *info, const char *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 206) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 207)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 208) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 209)   if( !info ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 210) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 211)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 212)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 213)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 214) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 215)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 216)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 217)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 218)     char cmd[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300 219)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 220)     pid_t p = (pid_t) -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 221)     int   rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 222) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 223)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 224)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 225)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 226)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 227)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 228)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 229)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 230) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 231)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 232)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 233)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 234)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 235) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 236)     if( revision && *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 237)       snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s log --pretty=format:'%%H' -1 %s 2>/dev/null", (char *)&path[0], revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 238)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 239)       snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s log --pretty=format:'%%H' -1 refs/heads/%s 2>/dev/null", (char *)&path[0], ctx.repo.trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300 240)     p = sys_exec_command( &buf, cmd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 241)     rc = sys_wait_command( p, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 242)     if( rc != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 243)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 244)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 245)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 246)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 247) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 248)     if( buf.buf[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 249)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 250)       strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 251)       strncpy( info->revision, buf.buf, GIT_OID_HEXSZ+1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 252)       fill_commit_info( info, (const char *)&path[0], NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 253)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 254) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 255)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 256) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 257)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 258)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 259) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 260) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 261) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 262) static const char *lang_info_by_path( const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 263) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 264)   char *lang = NULL, *name = NULL, *ext = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 265) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 266)   if( !path || !*path ) return (const char *)lang;
05d292b2 (kx 2023-03-24 03:51:10 +0300 267) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 268)   ext = rindex( path, '.' );
05d292b2 (kx 2023-03-24 03:51:10 +0300 269)   if( ext )
05d292b2 (kx 2023-03-24 03:51:10 +0300 270)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 271)     if( !strncasecmp( ext, ".mk", 3 )       ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 272)         !strncasecmp( ext, ".make", 5 )     ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 273)         !strncasecmp( ext, ".Makefile", 9 )   )
05d292b2 (kx 2023-03-24 03:51:10 +0300 274)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 275)       lang = (char *)__sbrk( 9 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 276)       sprintf( lang, "Makefile" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 277)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 278)     else if( !strncasecmp( ext, ".md", 3 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 279)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 280)       lang = (char *)__sbrk( 9 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 281)       sprintf( lang, "Markdown" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 282)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 283)     else if( !strncasecmp( ext, ".diff", 5 ) ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 284)              !strncasecmp( ext, ".patch", 6 )  )
05d292b2 (kx 2023-03-24 03:51:10 +0300 285)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 286)       lang = (char *)__sbrk( 9 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 287)       sprintf( lang, "Diff" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 288)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 289)     else if( !strncasecmp( ext, ".c", 2 ) ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 290)              !strncasecmp( ext, ".h", 2 )   )
05d292b2 (kx 2023-03-24 03:51:10 +0300 291)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 292)       lang = (char *)__sbrk( 2 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 293)       sprintf( lang, "C" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 294)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 295)     else if( !strncasecmp( ext, ".cpp", 4 ) ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 296)              !strncasecmp( ext, ".cxx", 4 ) ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 297)              !strncasecmp( ext, ".hpp", 4 )   )
05d292b2 (kx 2023-03-24 03:51:10 +0300 298)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 299)       lang = (char *)__sbrk( 4 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 300)       sprintf( lang, "C++" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 301)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 302)     else if( !strncasecmp( ext, ".html", 5 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 303)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 304)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 305)       sprintf( lang, "HTML" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 306)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 307)     else if( !strncasecmp( ext, ".css", 4 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 308)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 309)       lang = (char *)__sbrk( 4 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 310)       sprintf( lang, "CSS" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 311)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 312)     else if( !strncasecmp( ext, ".js", 3 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 313)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 314)       lang = (char *)__sbrk( 11 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 315)       sprintf( lang, "javascript" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 316)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 317)     else if( !strncasecmp( ext, ".json", 5 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 318)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 319)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 320)       sprintf( lang, "JSON" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 321)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 322)     else if( !strncasecmp( ext, ".less", 5 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 323)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 324)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 325)       sprintf( lang, "LESS" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 326)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 327)     else if( !strncasecmp( ext, ".scss", 5 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 328)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 329)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 330)       sprintf( lang, "SCSS" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 331)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 332)     else if( !strncasecmp( ext, ".pl", 3 ) ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 333)              !strncasecmp( ext, ".pm", 3 )   )
05d292b2 (kx 2023-03-24 03:51:10 +0300 334)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 335)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 336)       sprintf( lang, "Perl" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 337)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 338)     else if( !strncasecmp( ext, ".py", 3 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 339)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 340)       lang = (char *)__sbrk( 7 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 341)       sprintf( lang, "Python" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 342)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 343)     else if( !strncasecmp( ext, ".php", 4 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 344)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 345)       lang = (char *)__sbrk( 4 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 346)       sprintf( lang, "PHP" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 347)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 348)     else if( !strncasecmp( ext, ".txt", 4 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 349)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 350)       lang = (char *)__sbrk( 10 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 351)       sprintf( lang, "plaintext" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 352)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 353)     else if( !strncasecmp( ext, ".go", 3 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 354)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 355)       lang = (char *)__sbrk( 3 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 356)       sprintf( lang, "Go" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 357)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 358)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 359) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 360)   name = rindex( path, '/' );
05d292b2 (kx 2023-03-24 03:51:10 +0300 361)   if( name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 362)     ++name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 363)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 364)     name = (char *)path;
05d292b2 (kx 2023-03-24 03:51:10 +0300 365) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 366)   if( name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 367)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 368)     if( !strncasecmp( name, "Makefile", 8 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 369)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 370)       lang = (char *)__sbrk( 9 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 371)       sprintf( lang, "Makefile" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 372)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 373)     else if( !strcasecmp( name, "README" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 374)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 375)       lang = (char *)__sbrk( 10 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 376)       sprintf( lang, "Plaintext" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 377)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 378)     else if( !strcasecmp( name, "LICENSE" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 379)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 380)       lang = (char *)__sbrk( 10 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 381)       sprintf( lang, "Plaintext" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 382)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 383)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 384) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 385)   /***************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 386)     all chances are exhausted. probably highlight.js do it correctly...
05d292b2 (kx 2023-03-24 03:51:10 +0300 387)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300 388)   /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 389)   if( !lang )
05d292b2 (kx 2023-03-24 03:51:10 +0300 390)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 391)     lang = (char *)__sbrk( 10 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 392)     sprintf( lang, "plaintext" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 393)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 394)   */
05d292b2 (kx 2023-03-24 03:51:10 +0300 395) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 396)   return (const char *)lang;
05d292b2 (kx 2023-03-24 03:51:10 +0300 397) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 398) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 399) static const char *lang_info( const char *mime_type, const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 400) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 401)   char *lang = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 402) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 403)   if( !mime_type ) return (const char *)lang;
05d292b2 (kx 2023-03-24 03:51:10 +0300 404) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 405)   if( !strncmp( mime_type, "text/", 5 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 406)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 407)     if( !strncmp( mime_type, "text/x-c", 8 ) || !strncmp( mime_type, "text/x-csrc", 11 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 408)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 409)       lang = (char *)__sbrk( 2 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 410)       sprintf( lang, "C" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 411)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 412)     else if( !strncmp( mime_type, "text/x-perl", 11 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 413)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 414)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 415)       sprintf( lang, "Perl" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 416)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 417)     else if( !strncmp( mime_type, "text/x-diff", 11 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 418)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 419)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 420)       sprintf( lang, "Diff" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 421)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 422)     else if( !strncmp( mime_type, "text/x-makefile", 15 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 423)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 424)       lang = (char *)__sbrk( 9 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 425)       sprintf( lang, "Makefile" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 426)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 427)     else if( !strncmp( mime_type, "text/x-shell", 12 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 428)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 429)       lang = (char *)__sbrk( 5 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 430)       sprintf( lang, "Bash" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 431)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 432) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 433)     /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 434)       The 'text/plain;' mime type does not mean that the file contains plain text.
05d292b2 (kx 2023-03-24 03:51:10 +0300 435)       But we have to identify the language:
05d292b2 (kx 2023-03-24 03:51:10 +0300 436)      */
05d292b2 (kx 2023-03-24 03:51:10 +0300 437)     if( !lang && path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 438)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 439)       /* Here we can make lang identification by filename or extension */
05d292b2 (kx 2023-03-24 03:51:10 +0300 440)       lang = (char *)lang_info_by_path( path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 441)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 442)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 443) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 444)   return (const char *)lang;
05d292b2 (kx 2023-03-24 03:51:10 +0300 445) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 446) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 447) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 448) void cgit_rpath_info( struct cgit_info *info, const char *relative_path, const char *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 449) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 450)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 451) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 452)   if( !info || !relative_path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 453) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 454)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 455)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 456)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 457) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 458)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 459)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 460)     char ref[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 461)     char rpath[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 462) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 463)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 464)     char cmd[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300 465)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 466)     pid_t p = (pid_t) -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 467)     int   rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 468) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 469)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 470)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 471)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 472)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 473)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 474)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 475)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 476) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 477)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 478)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 479)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 480)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 481) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 482)     parse_relative_path( (char *)&ref[0], (char *)&rpath[0], relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 483) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 484)     if( revision && *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 485)       snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s log --pretty=format:'%%H' -1 %s -- %s 2>/dev/null", (char *)&path[0], revision, (char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 486)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 487)       snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s log --pretty=format:'%%H' -1 %s -- %s 2>/dev/null", (char *)&path[0], (char *)&ref[0], (char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 488)     p = sys_exec_command( &buf, cmd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 489)     rc = sys_wait_command( p, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 490)     if( rc != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 491)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 492)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 493)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 494)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 495) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 496)     if( buf.buf[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 497)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 498)       strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 499)       strncpy( info->revision, buf.buf, GIT_OID_HEXSZ+1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 500)       fill_commit_info( info, (const char *)&path[0], (const char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 501)       if( info->kind == GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300 502)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 503)         fill_mime_info( info, (const char *)&path[0], (const char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 504)         if( info->mode == GIT_FILEMODE_LINK )
05d292b2 (kx 2023-03-24 03:51:10 +0300 505)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 506)           int len = 10;
05d292b2 (kx 2023-03-24 03:51:10 +0300 507)           char *lang = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 508)           memcpy( (void *)lang, (const void *)"PlainText", len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 509)           info->lang = (const char *)lang;
05d292b2 (kx 2023-03-24 03:51:10 +0300 510)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 511)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 512)           info->lang = lang_info( (const char *)(info->mime), (const char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 513)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 514)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 515) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 516)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 517) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 518)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 519)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 520) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 521) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 522) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 523) void cgit_repo_branches_number( struct cgit_repository *rctx )
05d292b2 (kx 2023-03-24 03:51:10 +0300 524) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 525)   const char *name = NULL, *git_root = NULL, *repo_root = NULL, *trunk = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 526) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 527)   if( !rctx ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 528) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 529)   name      = rctx->name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 530)   git_root  = rctx->git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 531)   repo_root = rctx->repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 532)   trunk     = rctx->trunk;
05d292b2 (kx 2023-03-24 03:51:10 +0300 533) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 534)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 535)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 536)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 537)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 538)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 539)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 540)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 541)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 542)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 543)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 544) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 545)     if( trunk && *trunk )
05d292b2 (kx 2023-03-24 03:51:10 +0300 546)       rctx->nbranches = (int)branches_number( (const char *)&path[0], trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300 547)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 548)       rctx->nbranches = (int)branches_number( (const char *)&path[0], NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 549)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 550)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 551) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 552) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 553) void cgit_repo_tags_number( struct cgit_repository *rctx )
05d292b2 (kx 2023-03-24 03:51:10 +0300 554) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 555)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 556) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 557)   if( !rctx ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 558) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 559)   name      = rctx->name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 560)   git_root  = rctx->git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 561)   repo_root = rctx->repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 562) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 563)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 564)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 565)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 566)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 567)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 568)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 569)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 570)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 571)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 572)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 573) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 574)     rctx->ntags = (int)tags_number( (const char *)&path[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 575)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 576)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 577) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 578) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 579) void cgit_repo_commits_number( struct cgit_repository *rctx )
05d292b2 (kx 2023-03-24 03:51:10 +0300 580) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 581)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 582) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 583)   if( !rctx ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 584) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 585)   name      = rctx->name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 586)   git_root  = rctx->git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 587)   repo_root = rctx->repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 588) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 589)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 590)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 591)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 592)     char cmd[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300 593)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 594)     pid_t p = (pid_t) -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 595)     int   rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 596) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 597)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 598)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 599)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 600)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 601)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 602)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 603)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 604) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 605)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 606)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 607)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 608)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 609) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 610)     /* all commits in repo:
05d292b2 (kx 2023-03-24 03:51:10 +0300 611)        snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s rev-list -9999 --all --count 2>/dev/null", (char *)&path[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 612)      */
05d292b2 (kx 2023-03-24 03:51:10 +0300 613)     snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s rev-list -9999 HEAD^{commit} --count 2>/dev/null", (char *)&path[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 614)     p = sys_exec_command( &buf, cmd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 615)     rc = sys_wait_command( p, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 616)     if( rc != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 617)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 618)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 619)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 620)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 621) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 622)     if( buf.buf[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 623)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 624)       strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 625)       rctx->ncommits = atoi( buf.buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 626)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 627) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 628)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 629)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 630)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 631) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 632) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 633) void cgit_git_version( struct cgit_versions *vctx )
05d292b2 (kx 2023-03-24 03:51:10 +0300 634) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 635)   char cmd[1024];
05d292b2 (kx 2023-03-24 03:51:10 +0300 636)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 637)   pid_t p = (pid_t) -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 638)   int   rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 639) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 640)   char *version = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 641)   int   len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 642) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 643)   if( !vctx ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 644) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 645)   snprintf( (char *)&cmd[0], 1024, "git --version 2>/dev/null | cut -f3 -d' '" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 646)   p = sys_exec_command( &buf, cmd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 647)   rc = sys_wait_command( p, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 648)   if( rc != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 649)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 650)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 651)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 652)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 653) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 654)   if( buf.buf[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 655)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 656)     strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 657) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 658)     len = (int)strlen( buf.buf ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 659)     version = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 660)     memcpy( (void *)version, (const void *)buf.buf, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 661)     vctx->git = (const char *)version;
05d292b2 (kx 2023-03-24 03:51:10 +0300 662)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 663) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 664)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 665) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 666)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 667) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 668) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 669) void cgit_nginx_version( struct cgit_versions *vctx )
05d292b2 (kx 2023-03-24 03:51:10 +0300 670) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 671)   char cmd[1024];
05d292b2 (kx 2023-03-24 03:51:10 +0300 672)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 673)   pid_t p = (pid_t) -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 674)   int   rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 675) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 676)   char *version = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 677)   int   len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 678) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 679)   if( !vctx ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 680) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 681)   snprintf( (char *)&cmd[0], 1024, "nginx -v 2>&1 | cut -f2 -d'/'" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 682)   p = sys_exec_command( &buf, cmd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 683)   rc = sys_wait_command( p, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 684)   if( rc != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 685)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 686)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 687)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 688)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 689) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 690)   if( buf.buf[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 691)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 692)     strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 693) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 694)     len = (int)strlen( buf.buf ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 695)     version = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 696)     memcpy( (void *)version, (const void *)buf.buf, (size_t)len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 697)     vctx->nginx = (const char *)version;
05d292b2 (kx 2023-03-24 03:51:10 +0300 698)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 699) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 700)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 701) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 702)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 703) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 704) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 705) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 706) void cgit_print_404_page( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 707) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 708)   FILE  *fp;
05d292b2 (kx 2023-03-24 03:51:10 +0300 709)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 710) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 711)   fp = xfopen( ctx.page.header, "r" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 712)   (void)strbuf_env_fread( &buf, fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 713)   fclose( fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 714) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 715)   strbuf_addf( &buf, "        <div class=\"content segment\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 716)   strbuf_addf( &buf, "          <div class=\"container\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 717)   strbuf_addf( &buf, "            <div class=\"cgit-main-content\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 718)   strbuf_addf( &buf, "              <h1>Requested resource not found</h1>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 719)   strbuf_addf( &buf, "              <p class='leading'>Please check the requested URL or try again later.</p>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 720)   strbuf_addf( &buf, "            </div> <!-- End of cgit-main-content -->\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 721)   strbuf_addf( &buf, "          </div> <!-- End of container -->\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 722)   strbuf_addf( &buf, "        </div> <!-- End of content segment -->\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 723) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 724)   fp = xfopen( ctx.page.footer, "r" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 725)   (void)strbuf_env_fread( &buf, fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 726)   fclose( fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 727) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 728)   ctx.page.size = buf.len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 729)   cgit_print_http_headers();
05d292b2 (kx 2023-03-24 03:51:10 +0300 730)   strbuf_write( &buf, STDOUT_FILENO );
05d292b2 (kx 2023-03-24 03:51:10 +0300 731)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 732) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 733) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 734) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 735) void cgit_print_raw_file( struct strbuf *sb, const char *mime )
05d292b2 (kx 2023-03-24 03:51:10 +0300 736) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 737)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 738)   char *p = (char *)mime;
05d292b2 (kx 2023-03-24 03:51:10 +0300 739) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 740)   char *http_format = "Date: %s\n"
05d292b2 (kx 2023-03-24 03:51:10 +0300 741)                       "Content-Type: %s\n"
05d292b2 (kx 2023-03-24 03:51:10 +0300 742)                       "Content-Length: %ld\n\n";
05d292b2 (kx 2023-03-24 03:51:10 +0300 743) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 744)   if( !sb || !mime ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 745) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 746)   while( *p && *p != ';' ) ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 747)   if( *p ) *p = '\0';
05d292b2 (kx 2023-03-24 03:51:10 +0300 748) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 749)   strbuf_addf( &buf, http_format, http_date( time(NULL) ), mime, sb->len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 750)   strbuf_addbuf( &buf, (const struct strbuf *)sb );
05d292b2 (kx 2023-03-24 03:51:10 +0300 751)   strbuf_write( &buf, STDOUT_FILENO );
05d292b2 (kx 2023-03-24 03:51:10 +0300 752)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 753) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 754)   exit( 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 755) }