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 <unistd.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  33) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  34) #include <git2.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  35) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  36) #include <nls.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  37) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  38) #include <defs.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  39) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  40) #include <fatal.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  41) #include <http.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  42) #include <html.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300  43) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  44) #include <cmpvers.h>
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) /********************************
05d292b2 (kx 2023-03-24 03:51:10 +0300  58)   Sorted dlist functions:
05d292b2 (kx 2023-03-24 03:51:10 +0300  59)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300  60) struct tree_line {
05d292b2 (kx 2023-03-24 03:51:10 +0300  61)   char           *name;
05d292b2 (kx 2023-03-24 03:51:10 +0300  62)   char           *revision;
05d292b2 (kx 2023-03-24 03:51:10 +0300  63)   git_filemode_t  mode;
05d292b2 (kx 2023-03-24 03:51:10 +0300  64)   git_time_t      date;
05d292b2 (kx 2023-03-24 03:51:10 +0300  65)   int             offset;
05d292b2 (kx 2023-03-24 03:51:10 +0300  66)   git_off_t       size;
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) static struct dlist *directories = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  70) static struct dlist *files       = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  71) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  72) static struct tree_line *tree_line_alloc( const char *name, const char *revision, git_filemode_t mode, git_time_t date, int offset, git_off_t size  )
05d292b2 (kx 2023-03-24 03:51:10 +0300  73) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  74)   struct tree_line *line = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  75)   line = (struct tree_line *)xmalloc( sizeof(struct tree_line) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  76) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  77)   if( name )     { line->name     = xstrdup( name );     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  78)   if( revision ) { line->revision = xstrdup( revision ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300  79) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  80)   if( mode ) line->mode = mode;
05d292b2 (kx 2023-03-24 03:51:10 +0300  81)   else       line->mode = GIT_FILEMODE_TREE;
05d292b2 (kx 2023-03-24 03:51:10 +0300  82) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  83)   if( date ) line->date = date;
05d292b2 (kx 2023-03-24 03:51:10 +0300  84)   else       line->date = -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  85) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  86)   if( size ) line->size = size;
05d292b2 (kx 2023-03-24 03:51:10 +0300  87)   else       line->size = 4096;
05d292b2 (kx 2023-03-24 03:51:10 +0300  88) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  89)   return line;
05d292b2 (kx 2023-03-24 03:51:10 +0300  90) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  91) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  92) static void __line_free( void *data, void *user_data )
05d292b2 (kx 2023-03-24 03:51:10 +0300  93) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  94)   struct tree_line *line = (struct tree_line *)data;
05d292b2 (kx 2023-03-24 03:51:10 +0300  95)   if( line )
05d292b2 (kx 2023-03-24 03:51:10 +0300  96)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  97)     if( line->name )     { free( line->name );     line->name     = NULL; }
05d292b2 (kx 2023-03-24 03:51:10 +0300  98)     if( line->revision ) { free( line->revision ); line->revision = NULL; }
05d292b2 (kx 2023-03-24 03:51:10 +0300  99) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 100)     free( line );
05d292b2 (kx 2023-03-24 03:51:10 +0300 101)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 102) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 103) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 104) static struct dlist *tree_lines_free( struct dlist *lines )
05d292b2 (kx 2023-03-24 03:51:10 +0300 105) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 106)   if( lines )
05d292b2 (kx 2023-03-24 03:51:10 +0300 107)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 108)     dlist_free( lines, __line_free );
05d292b2 (kx 2023-03-24 03:51:10 +0300 109)     lines = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 110)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 111)   return lines;
05d292b2 (kx 2023-03-24 03:51:10 +0300 112) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 113) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 114) static int __cmp_tree_lines_byname( const void *a, const void *b )
05d292b2 (kx 2023-03-24 03:51:10 +0300 115) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 116)   int ret = -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 117) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 118)   struct tree_line *line1 = (struct tree_line *)a;
05d292b2 (kx 2023-03-24 03:51:10 +0300 119)   struct tree_line *line2 = (struct tree_line *)b;
05d292b2 (kx 2023-03-24 03:51:10 +0300 120) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 121)   if( line1->name && line2->name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 122)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 123)     ret = strcmp( line1->name, line2->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 124)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 125)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 126)     return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 127) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 128)   return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 129) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 130) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 131) static int __cmp_tree_lines_bytag( const void *a, const void *b )
05d292b2 (kx 2023-03-24 03:51:10 +0300 132) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 133)   char *v1 = NULL, *v2 = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 134)   int   ret = -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 135) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 136)   struct tree_line *line1 = (struct tree_line *)a;
05d292b2 (kx 2023-03-24 03:51:10 +0300 137)   struct tree_line *line2 = (struct tree_line *)b;
05d292b2 (kx 2023-03-24 03:51:10 +0300 138) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 139)   if( line1->name && line2->name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 140)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 141)     v1 = line1->name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 142)     v2 = line2->name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 143)     while( *v1 && !isdigit( *v1 ) ) ++v1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 144)     while( *v2 && !isdigit( *v2 ) ) ++v2;
05d292b2 (kx 2023-03-24 03:51:10 +0300 145)     ret = strcmp( line1->name, line2->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 146)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 147)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 148)     return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 149) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 150)   if( !*v1 || !*v2 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 151)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 152)     return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300 153)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 154) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 155)   /******************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 156)     sort reversive to show newest tag first:
05d292b2 (kx 2023-03-24 03:51:10 +0300 157)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300 158)   return -cmp_version( (const char *)v1, (const char *)v2 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 159) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 160) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 161) static struct dlist *tree_lines_sort_byname( struct dlist *lines )
05d292b2 (kx 2023-03-24 03:51:10 +0300 162) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 163)   if( lines ) { lines = dlist_sort( lines, __cmp_tree_lines_byname ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300 164)   return lines;
05d292b2 (kx 2023-03-24 03:51:10 +0300 165) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 166) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 167) static struct dlist *tree_lines_sort_bytag( struct dlist *lines )
05d292b2 (kx 2023-03-24 03:51:10 +0300 168) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 169)   if( lines ) { lines = dlist_sort( lines, __cmp_tree_lines_bytag ); }
05d292b2 (kx 2023-03-24 03:51:10 +0300 170)   return lines;
05d292b2 (kx 2023-03-24 03:51:10 +0300 171) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 172) /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 173)   End of sorted dlist functions.
05d292b2 (kx 2023-03-24 03:51:10 +0300 174)  ********************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 175) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 176) static void cgit_print_branches( struct strbuf *sb, const char *relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 177) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 178)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 179)   git_reference_iterator *iter = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 180)   const char *name = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 181)   const char *refs = "refs/heads/*";
05d292b2 (kx 2023-03-24 03:51:10 +0300 182) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 183)   const char *query_string = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 184) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 185)   if( !sb || !relative_path || !*relative_path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 186) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 187)   query_string = ctx_remove_query_param( ctx.env.query_string, "rev" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 188)   query_string = ctx_remove_query_param( query_string, "op" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 189) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 190)   if( !(repo = cgit_open_repository()) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 191) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 192)   if( git_reference_iterator_glob_new( &iter, repo, refs ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 193)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 194)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 195)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 196)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 197) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 198)   strbuf_addstr( sb, "\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 199)   strbuf_addf( sb, "              <div class=\"repo-tree-header\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 200)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 201)   strbuf_addf( sb, "                  <div class=\"col-path\">Path</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 202)   strbuf_addf( sb, "                  <div class=\"col-size\"><div class=\"tree-size trunc\">Size</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 203)   strbuf_addf( sb, "                  <div class=\"col-rev\"><div class=\"tree-rev trunc\">Rev</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 204)   strbuf_addf( sb, "                  <div class=\"col-date\"><div class=\"tree-date trunc\">Date</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 205)   strbuf_addf( sb, "                  <div class=\"col-links\"><div class=\"tree-links trunc\">Links</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 206)   strbuf_addf( sb, "                </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 207)   strbuf_addf( sb, "              </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 208)   strbuf_addf( sb, "              <div class=\"tree\">\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 209) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 210)   while( !git_reference_next_name( &name, iter ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 211)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 212)     struct tree_line *line = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 213)     git_commit       *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 214)     const git_oid    *oid;
05d292b2 (kx 2023-03-24 03:51:10 +0300 215)     git_time_t        date;
05d292b2 (kx 2023-03-24 03:51:10 +0300 216)     int               offset;
05d292b2 (kx 2023-03-24 03:51:10 +0300 217)     char id[GIT_OID_HEXSZ+1] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 218) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 219)     if( !(commit = get_commit_by_ref( repo, name )) ) continue;
05d292b2 (kx 2023-03-24 03:51:10 +0300 220) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 221)     oid     = git_commit_id( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 222)     date    = git_commit_time( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 223)     offset  = git_commit_time_offset( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 224) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 225)     offset = (offset % 60) + ((offset / 60) * 100);
05d292b2 (kx 2023-03-24 03:51:10 +0300 226) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 227)     if( git_oid_fmt( (char *)&id[0], oid ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 228)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 229)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 230)       continue;
05d292b2 (kx 2023-03-24 03:51:10 +0300 231)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 232) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 233)     line = tree_line_alloc( (const char *)&name[11], (const char *)&id[0], 0, date, offset, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 234)     directories = dlist_append( directories, (void *)line );
05d292b2 (kx 2023-03-24 03:51:10 +0300 235) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 236)     git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 237)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 238) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 239)   git_reference_iterator_free( iter );
05d292b2 (kx 2023-03-24 03:51:10 +0300 240)   close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 241) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 242)   /*************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 243)     Print directories list:
05d292b2 (kx 2023-03-24 03:51:10 +0300 244)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300 245)   if( directories )
05d292b2 (kx 2023-03-24 03:51:10 +0300 246)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 247)     struct dlist *list = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 248) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 249)     directories = tree_lines_sort_byname( directories );
05d292b2 (kx 2023-03-24 03:51:10 +0300 250) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 251)     list = directories;
05d292b2 (kx 2023-03-24 03:51:10 +0300 252) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 253)     while( list )
05d292b2 (kx 2023-03-24 03:51:10 +0300 254)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 255)       struct tree_line *line = (struct tree_line *)list->data;
05d292b2 (kx 2023-03-24 03:51:10 +0300 256) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 257)       if( strcmp( line->name, ctx.repo.trunk ) ) /* Do not print Trunk. */
05d292b2 (kx 2023-03-24 03:51:10 +0300 258)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 259)         /*************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 260)           Print branch Reference:
05d292b2 (kx 2023-03-24 03:51:10 +0300 261)          */
05d292b2 (kx 2023-03-24 03:51:10 +0300 262)         strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 263)         if( ctx.env.query_string && *ctx.env.query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 264)           strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/branches/%s/?%s\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, line->name, ctx.env.query_string, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 265)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 266)           strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/branches/%s/\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, line->name, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 267)         strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">%ld</div></div>\n", line->size );
05d292b2 (kx 2023-03-24 03:51:10 +0300 268)         strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\"><span class=\"rev-short\" title=\"%s\">%0.8s</span></div></div>\n", line->revision, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 269)         if( line->date != -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 270)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 271)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 272)           cgit_print_age( sb, (time_t)line->date, line->offset, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 273)           strbuf_addf( sb, "</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 274)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 275)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 276)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 277)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">unknown</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 278)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 279)         strbuf_addf( sb, "                  <div class=\"col-links\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 280)         strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 281)         if( query_string && *query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 282)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 283)           strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/branches/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 284)           strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/branches/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.name, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 285)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 286)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 287)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 288)           strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/branches/%s/?op=log&rev=%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 289)           strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/branches/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.name, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 290)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 291)         strbuf_addf( sb, "                    </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 292)         strbuf_addf( sb, "                  </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 293)         strbuf_addf( sb, "                </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 294)         /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 295)           End of printing.
05d292b2 (kx 2023-03-24 03:51:10 +0300 296)          *************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 297)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 298) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 299)       list = dlist_next( list );
05d292b2 (kx 2023-03-24 03:51:10 +0300 300)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 301)     directories = tree_lines_free( directories );
05d292b2 (kx 2023-03-24 03:51:10 +0300 302)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 303) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 304)   strbuf_addf( sb, "              </div> <!-- End of Tree -->\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 305) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 306) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 307) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 308) static void cgit_print_tags( struct strbuf *sb, const char *relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 309) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 310)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 311)   git_reference_iterator *iter = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 312)   const char *name = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 313)   const char *refs = "refs/tags/*";
05d292b2 (kx 2023-03-24 03:51:10 +0300 314) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 315)   const char *query_string = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 316) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 317)   if( !sb || !relative_path || !*relative_path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 318) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 319)   query_string = ctx_remove_query_param( ctx.env.query_string, "rev" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 320)   query_string = ctx_remove_query_param( query_string, "op" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 321) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 322)   if( !(repo = cgit_open_repository()) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 323) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 324)   if( git_reference_iterator_glob_new( &iter, repo, refs ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 325)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 326)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 327)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 328)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 329) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 330)   strbuf_addstr( sb, "\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 331)   strbuf_addf( sb, "              <div class=\"repo-tree-header\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 332)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 333)   strbuf_addf( sb, "                  <div class=\"col-path\">Path</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 334)   strbuf_addf( sb, "                  <div class=\"col-size\"><div class=\"tree-size trunc\">Size</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 335)   strbuf_addf( sb, "                  <div class=\"col-rev\"><div class=\"tree-rev trunc\">Rev</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 336)   strbuf_addf( sb, "                  <div class=\"col-date\"><div class=\"tree-date trunc\">Date</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 337)   strbuf_addf( sb, "                  <div class=\"col-links\"><div class=\"tree-links trunc\">Links</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 338)   strbuf_addf( sb, "                </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 339)   strbuf_addf( sb, "              </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 340)   strbuf_addf( sb, "              <div class=\"tree\">\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 341) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 342)   while( !git_reference_next_name( &name, iter ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 343)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 344)     struct tree_line *line = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 345)     git_commit       *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 346)     const git_oid    *oid;
05d292b2 (kx 2023-03-24 03:51:10 +0300 347)     git_time_t        date;
05d292b2 (kx 2023-03-24 03:51:10 +0300 348)     int               offset;
05d292b2 (kx 2023-03-24 03:51:10 +0300 349)     char id[GIT_OID_HEXSZ+1] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 350) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 351)     if( !(commit = get_commit_by_ref( repo, name )) ) continue;
05d292b2 (kx 2023-03-24 03:51:10 +0300 352) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 353)     oid     = git_commit_id( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 354)     date    = git_commit_time( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 355)     offset  = git_commit_time_offset( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 356) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 357)     offset = (offset % 60) + ((offset / 60) * 100);
05d292b2 (kx 2023-03-24 03:51:10 +0300 358) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 359)     if( git_oid_fmt( (char *)&id[0], oid ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 360)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 361)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 362)       continue;
05d292b2 (kx 2023-03-24 03:51:10 +0300 363)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 364) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 365)     line = tree_line_alloc( (const char *)&name[10], (const char *)&id[0], 0, date, offset, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 366)     directories = dlist_append( directories, (void *)line );
05d292b2 (kx 2023-03-24 03:51:10 +0300 367) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 368)     git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 369)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 370) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 371)   git_reference_iterator_free( iter );
05d292b2 (kx 2023-03-24 03:51:10 +0300 372)   close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 373) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 374)   /*************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 375)     Print directories list:
05d292b2 (kx 2023-03-24 03:51:10 +0300 376)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300 377)   if( directories )
05d292b2 (kx 2023-03-24 03:51:10 +0300 378)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 379)     struct dlist *list = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 380) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 381)     directories = tree_lines_sort_bytag( directories );
05d292b2 (kx 2023-03-24 03:51:10 +0300 382) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 383)     list = directories;
05d292b2 (kx 2023-03-24 03:51:10 +0300 384) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 385)     while( list )
05d292b2 (kx 2023-03-24 03:51:10 +0300 386)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 387)       struct tree_line *line = (struct tree_line *)list->data;
05d292b2 (kx 2023-03-24 03:51:10 +0300 388) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 389)       /**********************
05d292b2 (kx 2023-03-24 03:51:10 +0300 390)         Print tag Reference:
05d292b2 (kx 2023-03-24 03:51:10 +0300 391)        */
05d292b2 (kx 2023-03-24 03:51:10 +0300 392)       strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 393)       if( ctx.env.query_string && *ctx.env.query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 394)         strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/tags/%s/?%s\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, line->name, ctx.env.query_string, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 395)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 396)         strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/tags/%s/\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, line->name, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 397)       strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">%ld</div></div>\n", line->size );
05d292b2 (kx 2023-03-24 03:51:10 +0300 398)       strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\"><span class=\"rev-short\" title=\"%s\">%0.8s</span></div></div>\n", line->revision, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 399)       if( line->date != -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 400)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 401)         strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 402)         cgit_print_age( sb, (time_t)line->date, line->offset, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 403)         strbuf_addf( sb, "</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 404)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 405)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 406)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 407)         strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">unknown</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 408)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 409)       strbuf_addf( sb, "                  <div class=\"col-links\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 410)       strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 411)       if( query_string && *query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 412)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 413)         strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/tags/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 414)         strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/tags/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.name, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 415)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 416)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 417)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 418)         strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/tags/%s/?op=log&rev=%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 419)         strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/tags/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.name, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 420)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 421)       strbuf_addf( sb, "                    </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 422)       strbuf_addf( sb, "                  </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 423)       strbuf_addf( sb, "                </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 424)       /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 425)         End of printing.
05d292b2 (kx 2023-03-24 03:51:10 +0300 426)        **********************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 427) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 428)       list = dlist_next( list );
05d292b2 (kx 2023-03-24 03:51:10 +0300 429)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 430)     directories = tree_lines_free( directories );
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)   strbuf_addf( sb, "              </div> <!-- End of Tree -->\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 434) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 435) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 436) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 437) static void cgit_print_tree( struct strbuf *sb, const char *relative_path, const char *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 438) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 439)   struct cgit_info info = CGIT_INFO_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 440)   const char *query_string = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 441) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 442)   if( !sb || !relative_path || !*relative_path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 443) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 444)   if( !strcmp( relative_path, "tags"     ) ) return cgit_print_tags( sb, relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 445)   if( !strcmp( relative_path, "branches" ) ) return cgit_print_branches( sb, relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 446) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 447)   if( revision && strcmp( revision, (const char *)&ctx.repo.relative_info.revision[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 448)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 449)     cgit_rpath_info( &info, relative_path, revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 450)     if( info.kind != GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300 451)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 452)       strbuf_addf( sb, "              <h1>Requested resource cannot be shown</h1>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 453)       strbuf_addf( sb, "              <p class='leading'>The Tree with specified revision '%s' cannot be shown.</p>\n", revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 454)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 455)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 456)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 457)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 458)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 459)     memcpy( (void *)&info, (void *)&ctx.repo.relative_info, sizeof( struct cgit_info ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 460)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 461) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 462)   query_string = ctx_remove_query_param( ctx.env.query_string, "rev" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 463)   query_string = ctx_remove_query_param( query_string, "op" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 464) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 465)   strbuf_addstr( sb, "\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 466)   strbuf_addf( sb, "              <div class=\"repo-tree-header\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 467)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 468)   strbuf_addf( sb, "                  <div class=\"col-path\">Path</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 469)   strbuf_addf( sb, "                  <div class=\"col-size\"><div class=\"tree-size trunc\">Size</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 470)   strbuf_addf( sb, "                  <div class=\"col-rev\"><div class=\"tree-rev trunc\">Rev</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 471)   strbuf_addf( sb, "                  <div class=\"col-date\"><div class=\"tree-date trunc\">Date</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 472)   strbuf_addf( sb, "                  <div class=\"col-links\"><div class=\"tree-links trunc\">Links</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 473)   strbuf_addf( sb, "                </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 474)   strbuf_addf( sb, "              </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 475)   strbuf_addf( sb, "              <div class=\"tree\">\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 476) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 477)   if( info.kind == GIT_OBJECT_TREE )
05d292b2 (kx 2023-03-24 03:51:10 +0300 478)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 479)     git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 480)     git_tree       *tree = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 481)     git_oid         oid;
05d292b2 (kx 2023-03-24 03:51:10 +0300 482)     size_t          i, count;
05d292b2 (kx 2023-03-24 03:51:10 +0300 483)     char rpath[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 484) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 485)     if( git_oid_fromstr( &oid, (const char *)&info.oid[0] ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 486)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 487)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 488)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 489) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 490)     if( !(repo = cgit_open_repository()) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 491)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 492)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 493)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 494) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 495)     if( git_tree_lookup( &tree, repo, &oid ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 496)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 497)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 498)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 499)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 500) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 501)     count = git_tree_entrycount( tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300 502)     for( i = 0; i < count; ++i )
05d292b2 (kx 2023-03-24 03:51:10 +0300 503)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 504)       struct tree_line *line = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 505)       struct cgit_info entry_info = CGIT_INFO_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 506)       git_object *obj = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 507)       git_off_t   rawsize = 4096;
05d292b2 (kx 2023-03-24 03:51:10 +0300 508)       const git_tree_entry *entry = git_tree_entry_byindex( (const git_tree *)tree, i );
05d292b2 (kx 2023-03-24 03:51:10 +0300 509)       const char *name = git_tree_entry_name( entry ); /* filename */
05d292b2 (kx 2023-03-24 03:51:10 +0300 510) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 511)       git_tree_entry_to_object( &obj, repo, entry );
05d292b2 (kx 2023-03-24 03:51:10 +0300 512)       if( git_object_type( (const git_object *)obj ) == GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300 513)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 514)         rawsize = git_blob_rawsize( (git_blob *)obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300 515)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 516)       git_object_free( obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300 517) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 518)       sprintf( (char *)&rpath[0], "%s/%s", relative_path, name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 519)       cgit_rpath_info( &entry_info, (char *)&rpath[0], info.revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 520) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 521)       line = tree_line_alloc( name, (const char *)&entry_info.revision[0], entry_info.mode, entry_info.date, entry_info.offset, rawsize );
05d292b2 (kx 2023-03-24 03:51:10 +0300 522) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 523)       if( entry_info.kind == GIT_OBJECT_TREE )
05d292b2 (kx 2023-03-24 03:51:10 +0300 524)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 525)         directories = dlist_append( directories, (void *)line );
05d292b2 (kx 2023-03-24 03:51:10 +0300 526)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 527)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300 528)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 529)         files = dlist_append( files, (void *)line );
05d292b2 (kx 2023-03-24 03:51:10 +0300 530)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 531)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 532) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 533)     git_tree_free( tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300 534)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 535) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 536) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 537)     /*************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 538)       Print directories list:
05d292b2 (kx 2023-03-24 03:51:10 +0300 539)      */
05d292b2 (kx 2023-03-24 03:51:10 +0300 540)     if( directories )
05d292b2 (kx 2023-03-24 03:51:10 +0300 541)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 542)       struct dlist *list = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 543) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 544)       directories = tree_lines_sort_byname( directories );
05d292b2 (kx 2023-03-24 03:51:10 +0300 545) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 546)       list = directories;
05d292b2 (kx 2023-03-24 03:51:10 +0300 547) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 548)       while( list )
05d292b2 (kx 2023-03-24 03:51:10 +0300 549)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 550)         const char *mode = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 551)         struct tree_line *line = (struct tree_line *)list->data;
05d292b2 (kx 2023-03-24 03:51:10 +0300 552) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 553)         if( line->mode == GIT_FILEMODE_LINK )
05d292b2 (kx 2023-03-24 03:51:10 +0300 554)           mode = " link";
05d292b2 (kx 2023-03-24 03:51:10 +0300 555)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 556)           mode = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 557) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 558)         /*************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 559)           Print branch Reference:
05d292b2 (kx 2023-03-24 03:51:10 +0300 560)          */
05d292b2 (kx 2023-03-24 03:51:10 +0300 561)         strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 562)         if( ctx.env.query_string && *ctx.env.query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 563)           strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s/%s/?%s\"><div class=\"tree-path dir%s\">%s/</div></a></div>\n", ctx.repo.name, relative_path, line->name, ctx.env.query_string, mode, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 564)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 565)           strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s/%s/\"><div class=\"tree-path dir%s\">%s/</div></a></div>\n", ctx.repo.name, relative_path, line->name, mode, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 566)         strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">%ld</div></div>\n", line->size );
05d292b2 (kx 2023-03-24 03:51:10 +0300 567)         strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\"><span class=\"rev-short\" title=\"%s\">%0.8s</span></div></div>\n", line->revision, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 568)         if( line->date != -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 569)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 570)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 571)           cgit_print_age( sb, (time_t)line->date, line->offset, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 572)           strbuf_addf( sb, "</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 573)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 574)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 575)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 576)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">unknown</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 577)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 578)         strbuf_addf( sb, "                  <div class=\"col-links\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 579)         strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 580)         if( query_string && *query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 581)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 582)           strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, relative_path, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 583)           strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/%s/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.name, relative_path, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 584)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 585)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 586)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 587)           strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, relative_path, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 588)           strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/%s/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.name, relative_path, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 589)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 590)         strbuf_addf( sb, "                    </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 591)         strbuf_addf( sb, "                  </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 592)         strbuf_addf( sb, "                </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 593)         /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 594)           End of printing.
05d292b2 (kx 2023-03-24 03:51:10 +0300 595)          *************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 596) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 597)         list = dlist_next( list );
05d292b2 (kx 2023-03-24 03:51:10 +0300 598)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 599)       directories = tree_lines_free( directories );
05d292b2 (kx 2023-03-24 03:51:10 +0300 600)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 601) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 602)     /********************
05d292b2 (kx 2023-03-24 03:51:10 +0300 603)       Print filess list:
05d292b2 (kx 2023-03-24 03:51:10 +0300 604)      */
05d292b2 (kx 2023-03-24 03:51:10 +0300 605)     if( files )
05d292b2 (kx 2023-03-24 03:51:10 +0300 606)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 607)       struct dlist *list = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 608) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 609)       files = tree_lines_sort_byname( files );
05d292b2 (kx 2023-03-24 03:51:10 +0300 610) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 611)       list = files;
05d292b2 (kx 2023-03-24 03:51:10 +0300 612) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 613)       while( list )
05d292b2 (kx 2023-03-24 03:51:10 +0300 614)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 615)         const char *mode = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 616)         const char *mode_prefix = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 617)         struct tree_line *line = (struct tree_line *)list->data;
05d292b2 (kx 2023-03-24 03:51:10 +0300 618) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 619)         if( line->mode == GIT_FILEMODE_LINK )
05d292b2 (kx 2023-03-24 03:51:10 +0300 620)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 621)           mode = " link";
05d292b2 (kx 2023-03-24 03:51:10 +0300 622)           mode_prefix = "@";
05d292b2 (kx 2023-03-24 03:51:10 +0300 623)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 624)         else if( line->mode == GIT_FILEMODE_BLOB_EXECUTABLE )
05d292b2 (kx 2023-03-24 03:51:10 +0300 625)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 626)           mode = " exec";
05d292b2 (kx 2023-03-24 03:51:10 +0300 627)           mode_prefix = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 628)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 629)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 630)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 631)           mode = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 632)           mode_prefix = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 633)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 634) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 635)         /*************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 636)           Print branch Reference:
05d292b2 (kx 2023-03-24 03:51:10 +0300 637)          */
05d292b2 (kx 2023-03-24 03:51:10 +0300 638)         strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 639)         if( ctx.env.query_string && *ctx.env.query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 640)           strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s/%s/?%s\"><div class=\"tree-path file%s\">%s%s</div></a></div>\n", ctx.repo.name, relative_path, line->name, ctx.env.query_string, mode, mode_prefix, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 641)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 642)           strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s/%s/\"><div class=\"tree-path file%s\">%s%s</div></a></div>\n", ctx.repo.name, relative_path, line->name, mode, mode_prefix, line->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 643)         strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">%ld</div></div>\n", line->size );
05d292b2 (kx 2023-03-24 03:51:10 +0300 644)         strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\"><span class=\"rev-short\" title=\"%s\">%0.8s</span></div></div>\n", line->revision, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 645)         if( line->date != -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 646)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 647)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 648)           cgit_print_age( sb, (time_t)line->date, line->offset, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 649)           strbuf_addf( sb, "</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 650)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 651)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 652)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 653)           strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">unknown</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 654)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 655)         strbuf_addf( sb, "                  <div class=\"col-links\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 656)         strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 657)         if( query_string && *query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 658)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 659)           strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, relative_path, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 660)           strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/%s/%s/?op=diff&rev=%s&%s\">diff</a> &nbsp;\n", ctx.repo.name, relative_path, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 661)           strbuf_addf( sb, "                      <a href=\"/%s/%s/%s/?op=blame&rev=%s&%s\">blame</a>\n", ctx.repo.name, relative_path, line->name, line->revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 662)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 663)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 664)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 665)           strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", line->revision, ctx.repo.name, relative_path, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 666)           strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/%s/%s/?op=diff&rev=%s\">diff</a> &nbsp;\n", ctx.repo.name, relative_path, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 667)           strbuf_addf( sb, "                      <a href=\"/%s/%s/%s/?op=blame&rev=%s\">blame</a>\n", ctx.repo.name, relative_path, line->name, line->revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 668)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 669)         strbuf_addf( sb, "                    </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 670)         strbuf_addf( sb, "                  </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 671)         strbuf_addf( sb, "                </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 672)         /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 673)           End of printing.
05d292b2 (kx 2023-03-24 03:51:10 +0300 674)          *************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300 675) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 676)         list = dlist_next( list );
05d292b2 (kx 2023-03-24 03:51:10 +0300 677)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 678)       files = tree_lines_free( files );
05d292b2 (kx 2023-03-24 03:51:10 +0300 679)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 680)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 681) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 682)   strbuf_addf( sb, "              </div> <!-- End of Tree -->\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 683) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 684)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 685) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 686) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 687) static void cgit_print_summary( struct strbuf *sb, const char *relative_path, const char *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 688) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 689)   struct cgit_info  info;
05d292b2 (kx 2023-03-24 03:51:10 +0300 690)   const char       *query_string = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 691) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 692)   if( !sb ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 693) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 694)   if( relative_path && *relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 695)     return cgit_print_tree( sb, relative_path, revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 696) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 697)   query_string = ctx_remove_query_param( ctx.env.query_string, "rev" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 698)   query_string = ctx_remove_query_param( query_string, "op" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 699) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 700)   strbuf_addstr( sb, "\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 701)   strbuf_addf( sb, "              <div class=\"repo-tree-header\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 702)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 703)   strbuf_addf( sb, "                  <div class=\"col-path\">Refs</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 704)   strbuf_addf( sb, "                </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 705)   strbuf_addf( sb, "              </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 706)   strbuf_addf( sb, "              <div class=\"tree\">\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 707)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 708)   strbuf_addf( sb, "                  <div class=\"col-path\"><div class=\"tree-path dir\"><a href=\"/%s/branches/\">branches/</a></div></div>\n", ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 709)   strbuf_addf( sb, "                </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 710)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 711)   strbuf_addf( sb, "                  <div class=\"col-path\"><div class=\"tree-path dir\"><a href=\"/%s/tags/\">tags/</a></div></div>\n", ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 712)   strbuf_addf( sb, "                </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 713)   strbuf_addf( sb, "              </div> <!-- End of Tree -->\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 714) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 715)   cgit_rpath_info( &info, "/", revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 716)   if( info.kind != GIT_OBJECT_TREE && info.kind != GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300 717)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 718)     memcpy( (void *)&info, (const void *)&ctx.repo.relative_info, sizeof( struct cgit_info ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300 719)     ctx.query.revision = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 720)     (void)ctx_grab_str_query_param( "rev" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 721)     ctx.query.rev = "0";
05d292b2 (kx 2023-03-24 03:51:10 +0300 722)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 723) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 724)   strbuf_addstr( sb, "\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 725)   strbuf_addf( sb, "              <div class=\"repo-tree-header\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 726)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 727)   strbuf_addf( sb, "                  <div class=\"col-path\">Path</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 728)   strbuf_addf( sb, "                  <div class=\"col-size\"><div class=\"tree-size trunc\">Size</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 729)   strbuf_addf( sb, "                  <div class=\"col-rev\"><div class=\"tree-rev trunc\">Rev</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 730)   strbuf_addf( sb, "                  <div class=\"col-date\"><div class=\"tree-date trunc\">Date</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 731)   strbuf_addf( sb, "                  <div class=\"col-links\"><div class=\"tree-links trunc\">Links</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 732)   strbuf_addf( sb, "                </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 733)   strbuf_addf( sb, "              </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 734)   strbuf_addf( sb, "              <div class=\"tree\">\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 735) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 736)   /************************
05d292b2 (kx 2023-03-24 03:51:10 +0300 737)     Print trunk Reference:
05d292b2 (kx 2023-03-24 03:51:10 +0300 738)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300 739)   strbuf_addf( sb, "                <div class=\"row\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 740)   strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/trunk/\"><div class=\"tree-path dir\">trunk/</div></a></div>\n", ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 741)   strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">%ld</div></div>\n", (git_off_t)4096 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 742)   strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\"><span class=\"rev-short\" title=\"%s\">%0.8s</span></div></div>\n", info.revision, info.revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 743)   if( info.date != -1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 744)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 745)     strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 746)     cgit_print_age( sb, (time_t)info.date, info.offset, 0 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 747)     strbuf_addf( sb, "</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 748)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 749)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 750)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 751)     strbuf_addf( sb, "                  <div class=\"col-date\"><div onclick=\"trunc(this)\" class=\"tree-date trunc\">unknown</div></div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 752)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 753)   strbuf_addf( sb, "                  <div class=\"col-links\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 754)   strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 755)   if( query_string && *query_string )
05d292b2 (kx 2023-03-24 03:51:10 +0300 756)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 757)     strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/trunk/?op=log&rev=%s&%s\">log</a> &nbsp;\n", info.revision, ctx.repo.name, info.revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 758)     strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/trunk/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.name, info.revision, query_string );
05d292b2 (kx 2023-03-24 03:51:10 +0300 759)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 760)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 761)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 762)     strbuf_addf( sb, "                      <a title=\"Log from: %s\" href=\"/%s/trunk/?op=log&rev=%s\">log</a> &nbsp;\n", info.revision, ctx.repo.name, info.revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 763)     strbuf_addf( sb, "                      <a title=\"Compare with Previous\" href=\"/%s/trunk/?op=diff&rev=%s\">diff</a>\n", ctx.repo.name, info.revision );
05d292b2 (kx 2023-03-24 03:51:10 +0300 764)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 765)   strbuf_addf( sb, "                    </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 766)   strbuf_addf( sb, "                  </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 767)   strbuf_addf( sb, "                </div>\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 768) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 769)   strbuf_addf( sb, "              </div> <!-- End of Tree -->\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 770) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 771) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 772) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 773) static void cgit_print_clone_urls( struct strbuf *sb, const char *relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 774) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 775)   char  ref[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 776)   char  rpath[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 777)   char  branch[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 778) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 779)   if( !sb ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 780) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 781)   parse_relative_path( (char *)&ref[0], (char *)&rpath[0], relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 782) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 783)   if( ref[0] && strlen( (char *)&ref[0] ) > 11 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 784)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 785)     const char *b = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 786)     if( !strncmp( (char *)&ref[0], "refs/heads/", 11 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 787)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 788)       b = (const char *)&ref[11];
05d292b2 (kx 2023-03-24 03:51:10 +0300 789)       sprintf( (char *)&branch[0], "--branch %s -- ", b );
05d292b2 (kx 2023-03-24 03:51:10 +0300 790)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 791) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 792)     if( b && !strcmp( b, ctx.repo.trunk ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 793)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 794)       branch[0] = '\0';
05d292b2 (kx 2023-03-24 03:51:10 +0300 795)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 796)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 797) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 798)   strbuf_addf( sb, "              <div class=\"clone-box\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 799)   strbuf_addf( sb, "                <div class=\"clone-header\">Clone</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 800)   strbuf_addf( sb, "                <div class=\"clone-urls\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 801)   strbuf_addf( sb, "                  <div class=\"clone-line\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 802)   strbuf_addf( sb, "                    <div class=\"clone-perms\">ro:</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 803) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 804)   strbuf_addf( sb, "                    <div class=\"clone-url\">git clone %s%s/%s</div>\n", branch, ctx.repo.clone_ro_prefix, ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 805) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 806)   strbuf_addf( sb, "                  </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 807)   if( ctx.repo.clone_prefix && *ctx.repo.clone_prefix )
05d292b2 (kx 2023-03-24 03:51:10 +0300 808)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 809)     strbuf_addf( sb, "                  <div class=\"clone-line\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 810)     strbuf_addf( sb, "                    <div class=\"clone-perms\">rw:</div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 811) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 812)     strbuf_addf( sb, "                    <div class=\"clone-url\">git clone %s%s/%s</div>\n", branch, ctx.repo.clone_prefix, ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 813) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 814)     strbuf_addf( sb, "                  </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 815)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 816)   strbuf_addf( sb, "                </div>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 817)   strbuf_addf( sb, "              </div> <!-- End of Clone -->\n\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 818) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 819) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 820) void cgit_print_tree_page( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 821) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 822)   FILE  *fp;
05d292b2 (kx 2023-03-24 03:51:10 +0300 823)   struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 824) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 825)   fp = xfopen( ctx.page.header, "r" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 826)   (void)strbuf_env_fread( &buf, fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 827)   fclose( fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 828) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 829)   strbuf_addf( &buf, "        <div class=\"content segment\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 830)   strbuf_addf( &buf, "          <div class=\"container\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 831)   strbuf_addf( &buf, "            <div class=\"cgit-main-content\">\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 832) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 833)   if( ctx.repo.relative_info.kind == GIT_OBJECT_TREE )
05d292b2 (kx 2023-03-24 03:51:10 +0300 834)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 835)     if( ctx.repo.name )
05d292b2 (kx 2023-03-24 03:51:10 +0300 836)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 837)       cgit_print_summary( &buf, ctx.repo.relative_path, (!strcmp( ctx.query.rev, "0" )) ? (const char *)&ctx.repo.relative_info.revision[0] : ctx.query.rev );
05d292b2 (kx 2023-03-24 03:51:10 +0300 838)       cgit_print_clone_urls( &buf, ctx.repo.relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 839)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 840)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 841)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 842)       strbuf_addf( &buf, "              <h1>Requested resource cannot be shown</h1>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 843)       strbuf_addf( &buf, "              <p class='leading'>Repository '%s' not found.</p>\n", ctx.repo.name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 844)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 845)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 846)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300 847)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 848)     strbuf_addf( &buf, "              <h1>Requested resource cannot be shown</h1>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 849)     strbuf_addf( &buf, "              <p class='leading'>This page assume the repository tree to be shown.</p>\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 850)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 851) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 852)   strbuf_addf( &buf, "            </div> <!-- End of cgit-main-content -->\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 853)   strbuf_addf( &buf, "          </div> <!-- End of container -->\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 854)   strbuf_addf( &buf, "        </div> <!-- End of content segment -->\n" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 855) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 856)   fp = xfopen( ctx.page.footer, "r" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 857)   (void)strbuf_env_fread( &buf, fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 858)   fclose( fp );
05d292b2 (kx 2023-03-24 03:51:10 +0300 859) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 860)   ctx.page.size = buf.len;
05d292b2 (kx 2023-03-24 03:51:10 +0300 861)   cgit_print_http_headers();
05d292b2 (kx 2023-03-24 03:51:10 +0300 862)   strbuf_write( &buf, STDOUT_FILENO );
05d292b2 (kx 2023-03-24 03:51:10 +0300 863)   strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 864) }