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) #include <stdint.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   11) #include <dirent.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   12) #include <sys/stat.h> /* chmod(2)    */
05d292b2 (kx 2023-03-24 03:51:10 +0300   13) #include <sys/file.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   14) #include <sys/mman.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   15) #include <fcntl.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   16) #include <limits.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   17) #include <string.h>   /* strdup(3)   */
05d292b2 (kx 2023-03-24 03:51:10 +0300   18) #include <libgen.h>   /* basename(3) */
05d292b2 (kx 2023-03-24 03:51:10 +0300   19) #include <ctype.h>    /* tolower(3)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300   20) #include <errno.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   21) #include <time.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   22) #include <sys/time.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   23) #include <pwd.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   24) #include <grp.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   25) #include <stdarg.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   26) #include <unistd.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   27) #include <magic.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   28) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   29) #include <git2.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   30) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   31) #include <nls.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   32) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   33) #include <defs.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   34) #include <fatal.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   35) #include <http.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   36) #include <html.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   37) #include <strbuf.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   38) #include <wrapper.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   39) #include <system.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   40) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   41) #include <ctx.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   42) #include <git-shared.h>
05d292b2 (kx 2023-03-24 03:51:10 +0300   43) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   44) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   45) #define CGIT_ERRMSG_SIZE 4096
05d292b2 (kx 2023-03-24 03:51:10 +0300   46) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   47) void cgit_error( const char *fmt, ... )
05d292b2 (kx 2023-03-24 03:51:10 +0300   48) {
05d292b2 (kx 2023-03-24 03:51:10 +0300   49)   va_list arg_ptr;
05d292b2 (kx 2023-03-24 03:51:10 +0300   50)   char  buf[CGIT_ERRMSG_SIZE];
05d292b2 (kx 2023-03-24 03:51:10 +0300   51)   char  msg[CGIT_ERRMSG_SIZE];
05d292b2 (kx 2023-03-24 03:51:10 +0300   52)   char *format = "%s: %s\n";
05d292b2 (kx 2023-03-24 03:51:10 +0300   53) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   54)   va_start( arg_ptr, fmt );
05d292b2 (kx 2023-03-24 03:51:10 +0300   55) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   56)   vsnprintf( msg, CGIT_ERRMSG_SIZE, (const void *)fmt, arg_ptr );
05d292b2 (kx 2023-03-24 03:51:10 +0300   57) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   58)   va_end( arg_ptr ); /* Reset variable arguments. */
05d292b2 (kx 2023-03-24 03:51:10 +0300   59) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   60)   snprintf( buf, CGIT_ERRMSG_SIZE, format, "cgit", msg );
05d292b2 (kx 2023-03-24 03:51:10 +0300   61) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   62)   (void)write( STDERR_FILENO, buf, strlen( buf ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300   63) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   64)   exit( 1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300   65) }
05d292b2 (kx 2023-03-24 03:51:10 +0300   66) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   67) cgit_errfunc cgit_fatal = cgit_error;
05d292b2 (kx 2023-03-24 03:51:10 +0300   68) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   69) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   70) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   71) int is_bare( const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300   72) {
05d292b2 (kx 2023-03-24 03:51:10 +0300   73)   char *p = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300   74)   int   ret = -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300   75) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   76)   if( !path || !*path ) return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300   77) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   78)   p = rindex( path, '.' );
05d292b2 (kx 2023-03-24 03:51:10 +0300   79)   if( !p )
05d292b2 (kx 2023-03-24 03:51:10 +0300   80)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300   81)     ret = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300   82)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300   83)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300   84)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300   85)     if( !strncmp( p, ".git", 4 ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300   86)       ret = 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300   87)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300   88)       ret = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300   89)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300   90) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   91)   return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300   92) }
05d292b2 (kx 2023-03-24 03:51:10 +0300   93) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   94) git_repository *open_repository( const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300   95) {
05d292b2 (kx 2023-03-24 03:51:10 +0300   96)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300   97)   int bare = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300   98) 
05d292b2 (kx 2023-03-24 03:51:10 +0300   99)   if( (bare = is_bare( path )) < 0 ) return repo;
05d292b2 (kx 2023-03-24 03:51:10 +0300  100) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  101)   if( bare )
05d292b2 (kx 2023-03-24 03:51:10 +0300  102)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  103)     if( git_repository_open_bare( &repo, path ) < 0 ) return repo;
05d292b2 (kx 2023-03-24 03:51:10 +0300  104)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  105)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300  106)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  107)     if( git_repository_open( &repo, path ) < 0 ) return repo;
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)   return repo;
05d292b2 (kx 2023-03-24 03:51:10 +0300  111) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  112) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  113) void close_repository( git_repository *repo )
05d292b2 (kx 2023-03-24 03:51:10 +0300  114) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  115)   if( !repo ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  116)   git_repository_free( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  117) }
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)   Get Last Commit:
05d292b2 (kx 2023-03-24 03:51:10 +0300  121)   (Only commit-ish refs are permitted)
05d292b2 (kx 2023-03-24 03:51:10 +0300  122)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300  123) git_commit *get_commit_by_ref( git_repository *repo, const char *ref )
05d292b2 (kx 2023-03-24 03:51:10 +0300  124) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  125)   int error = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  126)   git_object *obj = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  127)   git_commit *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  128) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  129)   char reference[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  130) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  131)   if( !repo ) return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300  132)   if( !ref ) ref = "HEAD^{commit}";
05d292b2 (kx 2023-03-24 03:51:10 +0300  133) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  134)   sprintf( (char *)&reference[0], "%s^{commit}", ref );
05d292b2 (kx 2023-03-24 03:51:10 +0300  135) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  136)   error = git_revparse_single( &obj, repo, (const char *)&reference[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300  137)   if( error < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  138)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  139)     git_error_clear();
05d292b2 (kx 2023-03-24 03:51:10 +0300  140)     return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300  141)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  142) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  143)   if( git_object_type(obj) != GIT_OBJECT_COMMIT )
05d292b2 (kx 2023-03-24 03:51:10 +0300  144)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  145)     git_object_free( obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300  146)     return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300  147)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  148) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  149)   error = git_commit_lookup( &commit, repo, git_object_id( obj ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  150)   if( error < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  151)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  152)     git_error_clear();
05d292b2 (kx 2023-03-24 03:51:10 +0300  153)     git_object_free( obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300  154)     return NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  155)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  156) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  157)   git_object_free( obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300  158) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  159)   return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300  160) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  161) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  162) git_commit *get_commit_by_hex( git_repository *repo, const char *hex )
05d292b2 (kx 2023-03-24 03:51:10 +0300  163) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  164)   git_oid     cid;
05d292b2 (kx 2023-03-24 03:51:10 +0300  165)   git_commit *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  166) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  167)   if( !repo || !hex ) return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300  168)   if( git_oid_fromstr( &cid, hex ) < 0 ) return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300  169) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  170)   if( git_commit_lookup( &commit, repo, &cid ) < 0 ) return NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  171)   return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300  172) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  173) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  174) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  175) void fill_short_commit_info( struct short_commit_info *info, const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300  176) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  177)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  178)   git_commit     *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  179) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  180)   if( !info || !path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  181) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  182)   if( !(repo = open_repository( path )) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  183) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  184)   if( !(commit = get_commit_by_ref( repo, NULL )) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  185)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  186)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  187)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  188)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  189) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  190)   git_oid_tostr( info->rev, GIT_OID_HEXSZ+1, git_commit_id( commit ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  191)   info->date   = git_commit_time( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  192)   info->offset = git_commit_time_offset( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  193) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  194)   info->offset = (info->offset % 60) + ((info->offset / 60) * 100);
05d292b2 (kx 2023-03-24 03:51:10 +0300  195) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  196)   git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  197) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  198)   close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  199) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  200) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  201) struct found {
05d292b2 (kx 2023-03-24 03:51:10 +0300  202)   git_object_t    kind;
05d292b2 (kx 2023-03-24 03:51:10 +0300  203)   git_filemode_t  mode;
05d292b2 (kx 2023-03-24 03:51:10 +0300  204)   const git_oid  *oid;
05d292b2 (kx 2023-03-24 03:51:10 +0300  205)   git_object     *obj;
05d292b2 (kx 2023-03-24 03:51:10 +0300  206) };
05d292b2 (kx 2023-03-24 03:51:10 +0300  207) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  208) static void find_entry( struct found *ret, git_repository *repo, git_tree *tree, char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300  209) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  210)   git_tree     *ntree = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  211)   int           i, cnt;
05d292b2 (kx 2023-03-24 03:51:10 +0300  212)   char         *s, *p = NULL, *n;
05d292b2 (kx 2023-03-24 03:51:10 +0300  213) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  214)   if( !ret || !repo || !tree ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  215) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  216)   if( path && *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300  217)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  218)     s = path;
05d292b2 (kx 2023-03-24 03:51:10 +0300  219) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  220)     while( *s &&  *s == '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  221)       ++s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  222)     n = p = s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  223) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  224)     while( *p && *p != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  225)       ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  226)     if( *p )
05d292b2 (kx 2023-03-24 03:51:10 +0300  227)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  228)       *p = '\0'; s = ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  229)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  230)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300  231)       s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  232) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  233)     git_tree_dup( &ntree, tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  234)     cnt = git_tree_entrycount( ntree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  235) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  236)     for( i = 0; i < cnt; ++i )
05d292b2 (kx 2023-03-24 03:51:10 +0300  237)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  238)       const git_tree_entry *entry;
05d292b2 (kx 2023-03-24 03:51:10 +0300  239)       entry = git_tree_entry_byindex( ntree, i );
05d292b2 (kx 2023-03-24 03:51:10 +0300  240) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  241)       if( !strcmp( git_tree_entry_name( entry ), n ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  242)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  243)         ret->kind = git_tree_entry_type( entry );
05d292b2 (kx 2023-03-24 03:51:10 +0300  244)         ret->mode = git_tree_entry_filemode( entry );
05d292b2 (kx 2023-03-24 03:51:10 +0300  245)         git_tree_entry_to_object( &ret->obj, repo, entry );
05d292b2 (kx 2023-03-24 03:51:10 +0300  246)         ret->oid = git_object_id( (const git_object *)ret->obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300  247) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  248)         if( ret->kind == GIT_OBJECT_TREE && s && *s )
05d292b2 (kx 2023-03-24 03:51:10 +0300  249)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300  250)           git_object *obj;
05d292b2 (kx 2023-03-24 03:51:10 +0300  251)           git_tree_entry_to_object( &obj, repo, entry );
05d292b2 (kx 2023-03-24 03:51:10 +0300  252)           find_entry( ret, repo, (git_tree *)obj, s );
05d292b2 (kx 2023-03-24 03:51:10 +0300  253)           git_object_free( obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300  254)           break;
05d292b2 (kx 2023-03-24 03:51:10 +0300  255)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300  256)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300  257)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300  258)           break;
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)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  263)     git_tree_free( ntree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  264)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  265) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  266)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  267) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  268) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  269) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  270) void fill_commit_info( struct cgit_info *info, const char *path, const char *rpath )
05d292b2 (kx 2023-03-24 03:51:10 +0300  271) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  272)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  273)   git_oid         cid;
05d292b2 (kx 2023-03-24 03:51:10 +0300  274)   git_commit     *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  275)   git_tree       *tree = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  276)   const git_oid  *oid;
05d292b2 (kx 2023-03-24 03:51:10 +0300  277)   const git_signature *sign = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  278) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  279)   char *author;
05d292b2 (kx 2023-03-24 03:51:10 +0300  280)   int   len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  281) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  282)   if( !info || !path || !info->revision[0] ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  283)   if( git_oid_fromstr( &cid, (const char *)&info->revision[0] ) < 0 ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  284)   if( !(repo = open_repository( path )) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  285) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  286)   git_commit_lookup( &commit, repo, &cid );
05d292b2 (kx 2023-03-24 03:51:10 +0300  287)   git_commit_tree( &tree, commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  288) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  289)   info->kind = git_object_type( (const git_object *)tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  290)   oid = git_tree_id( (const git_tree *)tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  291)   git_oid_fmt( (char *)&info->oid[0], oid );
05d292b2 (kx 2023-03-24 03:51:10 +0300  292) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  293)   if( rpath && *rpath )
05d292b2 (kx 2023-03-24 03:51:10 +0300  294)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  295)     struct found  ret = { .kind = GIT_OBJECT_TREE, .oid = NULL, .obj = NULL };
05d292b2 (kx 2023-03-24 03:51:10 +0300  296)     char relative_path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  297)     sprintf( (char *)&relative_path[0], rpath );
05d292b2 (kx 2023-03-24 03:51:10 +0300  298)     find_entry( &ret, repo, tree, (char *)&relative_path[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300  299)     info->kind = ret.kind;
05d292b2 (kx 2023-03-24 03:51:10 +0300  300)     info->mode = ret.mode;
05d292b2 (kx 2023-03-24 03:51:10 +0300  301)     git_oid_fmt( (char *)&info->oid[0], ret.oid );
05d292b2 (kx 2023-03-24 03:51:10 +0300  302)     git_object_free( ret.obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300  303)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  304) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  305)   git_tree_free( tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  306) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  307)   info->date = git_commit_time( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  308)   info->offset = git_commit_time_offset( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  309) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  310)   info->offset = (info->offset % 60) + ((info->offset / 60) * 100);
05d292b2 (kx 2023-03-24 03:51:10 +0300  311) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  312)   sign = git_commit_author( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  313)   len = (int)strlen( sign->name ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  314)   author = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300  315)   strcpy( author, sign->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300  316)   info->author = author;
05d292b2 (kx 2023-03-24 03:51:10 +0300  317) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  318)   git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  319)   close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  320) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  321) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  322) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  323) static const char *mime_info( struct cgit_info *info, const char *buffer, size_t length )
05d292b2 (kx 2023-03-24 03:51:10 +0300  324) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  325)   const char *mime = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  326)   magic_t     magic;
05d292b2 (kx 2023-03-24 03:51:10 +0300  327) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  328)   if( !info || !buffer || !length ) return mime;
05d292b2 (kx 2023-03-24 03:51:10 +0300  329) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  330)   magic = magic_open( MAGIC_MIME );
05d292b2 (kx 2023-03-24 03:51:10 +0300  331)   if( !magic )
05d292b2 (kx 2023-03-24 03:51:10 +0300  332)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  333)     html_fatal( "unable to initialize magic library" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  334)     return mime;
05d292b2 (kx 2023-03-24 03:51:10 +0300  335)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  336)   if( magic_load( magic, NULL ) != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  337)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  338)     html_fatal( "cannot load magic database - %s\n", magic_error( magic ) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  339)     magic_close( magic );
05d292b2 (kx 2023-03-24 03:51:10 +0300  340)     return mime;
05d292b2 (kx 2023-03-24 03:51:10 +0300  341)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  342) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  343)   mime = magic_buffer( magic, buffer, length );
05d292b2 (kx 2023-03-24 03:51:10 +0300  344)   if( mime )
05d292b2 (kx 2023-03-24 03:51:10 +0300  345)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  346)     int len = (int)strlen( mime ) + 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  347)     char *mime_type = (char *)__sbrk( len );
05d292b2 (kx 2023-03-24 03:51:10 +0300  348)     memcpy( (void *)mime_type, (const void *)mime, len );
05d292b2 (kx 2023-03-24 03:51:10 +0300  349)     info->mime = (const char *)mime_type;
05d292b2 (kx 2023-03-24 03:51:10 +0300  350)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  351) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  352)   magic_close( magic );
05d292b2 (kx 2023-03-24 03:51:10 +0300  353)   return mime;
05d292b2 (kx 2023-03-24 03:51:10 +0300  354) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  355) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  356) void fill_mime_info( struct cgit_info *info, const char *path, const char *rpath )
05d292b2 (kx 2023-03-24 03:51:10 +0300  357) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  358)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  359)   git_oid         cid;
05d292b2 (kx 2023-03-24 03:51:10 +0300  360)   git_commit     *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  361)   git_tree       *tree = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  362)   git_object     *obj = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  363)   git_object_t    kind;
05d292b2 (kx 2023-03-24 03:51:10 +0300  364)   git_blob       *blob = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  365)   int             blob_allocated = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  366)   git_off_t       rawsize = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  367)   const char     *raw = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  368)   char            mime_buf[1024] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  369)   size_t          len = 1024;
05d292b2 (kx 2023-03-24 03:51:10 +0300  370) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  371)   if( !info || !path || !info->revision[0] || info->kind != GIT_OBJECT_BLOB ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  372)   if( git_oid_fromstr( &cid, (const char *)&info->revision[0] ) < 0 ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  373)   if( !(repo = open_repository( path )) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  374) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  375)   git_commit_lookup( &commit, repo, &cid );
05d292b2 (kx 2023-03-24 03:51:10 +0300  376)   git_commit_tree( &tree, commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  377) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  378)   blob = (git_blob *)tree;
05d292b2 (kx 2023-03-24 03:51:10 +0300  379)   kind = git_object_type( (const git_object *)tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  380)   if( rpath && *rpath )
05d292b2 (kx 2023-03-24 03:51:10 +0300  381)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  382)     struct found  ret = { .kind = GIT_OBJECT_TREE, .oid = NULL, .obj = NULL };
05d292b2 (kx 2023-03-24 03:51:10 +0300  383)     char relative_path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  384)     sprintf( (char *)&relative_path[0], rpath );
05d292b2 (kx 2023-03-24 03:51:10 +0300  385)     find_entry( &ret, repo, tree, (char *)&relative_path[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300  386)     kind = ret.kind;
05d292b2 (kx 2023-03-24 03:51:10 +0300  387)     if( kind == GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300  388)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  389)       git_object_dup( &obj, ret.obj );
05d292b2 (kx 2023-03-24 03:51:10 +0300  390)       blob_allocated = 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  391)       blob = (git_blob *)obj;
05d292b2 (kx 2023-03-24 03:51:10 +0300  392)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  393)     git_object_free( ret.obj ); /* We have to free allocated object returned by find_entry(). */
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)   if( kind != GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300  397)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  398)     if( blob_allocated )
05d292b2 (kx 2023-03-24 03:51:10 +0300  399)       git_object_free( (git_object *)blob );
05d292b2 (kx 2023-03-24 03:51:10 +0300  400)     git_tree_free( tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  401)     git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  402)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  403)     return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  404)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  405) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  406)   rawsize = git_blob_rawsize( blob );
05d292b2 (kx 2023-03-24 03:51:10 +0300  407)   raw = (const char *)git_blob_rawcontent( blob );
05d292b2 (kx 2023-03-24 03:51:10 +0300  408)   if( rawsize > 1024 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  409)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  410)     memcpy( (void *)&mime_buf[0], (const void *)raw, len );
05d292b2 (kx 2023-03-24 03:51:10 +0300  411)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  412)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300  413)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  414)     memcpy( (void *)&mime_buf[0], (const void *)raw, (size_t)rawsize );
05d292b2 (kx 2023-03-24 03:51:10 +0300  415)     len = (size_t)rawsize;
05d292b2 (kx 2023-03-24 03:51:10 +0300  416)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  417) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  418)   if( blob_allocated )
05d292b2 (kx 2023-03-24 03:51:10 +0300  419)     git_object_free( (git_object *)blob );
05d292b2 (kx 2023-03-24 03:51:10 +0300  420)   git_tree_free( tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300  421) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  422)   mime_info( info, (const char *)&mime_buf[0], len );
05d292b2 (kx 2023-03-24 03:51:10 +0300  423) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  424)   git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300  425)   close_repository( repo );
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) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  429) size_t branches_number( const char *path, const char *skip )
05d292b2 (kx 2023-03-24 03:51:10 +0300  430) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  431)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  432)   git_reference_iterator *iter = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  433)   const char *name = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  434)   size_t ret = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  435) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  436)   if( !path ) return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  437) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  438)   if( !(repo = open_repository( path )) ) return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  439) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  440)   if( git_reference_iterator_glob_new( &iter, repo, "refs/heads/*" ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  441)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  442)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  443)     return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  444)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  445) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  446)   while( !git_reference_next_name( &name, iter ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  447)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  448)     if( skip && *skip )
05d292b2 (kx 2023-03-24 03:51:10 +0300  449)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  450)       if( strcmp( (const char *)&name[11], skip ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  451)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  452)         ++ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  453)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  454)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  455)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300  456)       ++ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  457)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  458) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  459)   git_reference_iterator_free( iter );
05d292b2 (kx 2023-03-24 03:51:10 +0300  460)   close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  461) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  462)   return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  463) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  464) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  465) size_t tags_number( const char *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300  466) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  467)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  468)   git_strarray    tags;
05d292b2 (kx 2023-03-24 03:51:10 +0300  469)   size_t ret = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  470) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  471)   if( !path ) return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  472) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  473)   if( !(repo = open_repository( path )) ) return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  474) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  475)   if( git_tag_list( &tags, repo ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  476)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  477)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  478)     return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  479)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  480) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  481)   ret = tags.count;
05d292b2 (kx 2023-03-24 03:51:10 +0300  482)   git_strarray_free( &tags );
05d292b2 (kx 2023-03-24 03:51:10 +0300  483) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  484)   close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  485) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  486)   return ret;
05d292b2 (kx 2023-03-24 03:51:10 +0300  487) }
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)   List of references functions:
05d292b2 (kx 2023-03-24 03:51:10 +0300  491)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300  492) struct cgit_ref_names *cgit_ref_names_new( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  493) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  494)   struct cgit_ref_names *names = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  495) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  496)   names = (struct cgit_ref_names *)xmalloc( sizeof(struct cgit_ref_names) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  497)   return names;
05d292b2 (kx 2023-03-24 03:51:10 +0300  498) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  499) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  500) void cgit_ref_names_allocate( struct cgit_ref_names **ref_names )
05d292b2 (kx 2023-03-24 03:51:10 +0300  501) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  502)   struct cgit_ref_names *names = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  503) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  504)   if( !ref_names ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  505)   names = (struct cgit_ref_names *)xmalloc( sizeof(struct cgit_ref_names) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  506)   *ref_names = names;
05d292b2 (kx 2023-03-24 03:51:10 +0300  507) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  508) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  509) void cgit_ref_names_add( struct cgit_ref_names *names, const char *name )
05d292b2 (kx 2023-03-24 03:51:10 +0300  510) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  511)   if( !names ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  512) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  513)   if( !names->name )
05d292b2 (kx 2023-03-24 03:51:10 +0300  514)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  515)     names->name = (char **)xmalloc( sizeof(char *) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  516)     names->name[0] = strdup( name );
05d292b2 (kx 2023-03-24 03:51:10 +0300  517)     names->len = (size_t)1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  518)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  519)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300  520)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  521)     names->name = (char **)xrealloc( names->name, (names->len + 1) * sizeof(char *) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  522)     names->name[names->len] = strdup( name );
05d292b2 (kx 2023-03-24 03:51:10 +0300  523)     ++names->len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  524)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  525) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  526) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  527) void cgit_ref_names_free( struct cgit_ref_names *names )
05d292b2 (kx 2023-03-24 03:51:10 +0300  528) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  529)   if( !names ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  530) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  531)   if( names->len && names->name )
05d292b2 (kx 2023-03-24 03:51:10 +0300  532)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  533)     size_t i;
05d292b2 (kx 2023-03-24 03:51:10 +0300  534)     for( i = 0; i < names->len; ++i )
05d292b2 (kx 2023-03-24 03:51:10 +0300  535)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  536)       if( names->name[i] )
05d292b2 (kx 2023-03-24 03:51:10 +0300  537)         free( names->name[i] );
05d292b2 (kx 2023-03-24 03:51:10 +0300  538)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  539)     free( names->name );
05d292b2 (kx 2023-03-24 03:51:10 +0300  540)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  541)   free( names );
05d292b2 (kx 2023-03-24 03:51:10 +0300  542) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  543) /*
05d292b2 (kx 2023-03-24 03:51:10 +0300  544)   End of List of references functions.
05d292b2 (kx 2023-03-24 03:51:10 +0300  545)  **************************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300  546) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  547) void lookup_branches_by_prefix( struct cgit_ref_names **ref_names, const char *prefix )
05d292b2 (kx 2023-03-24 03:51:10 +0300  548) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  549)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  550)   struct cgit_ref_names *names = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  551) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  552)   if( !ref_names || !prefix || !*prefix ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  553) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  554)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300  555)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300  556)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300  557) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  558)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300  559)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  560)     git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  561)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  562) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  563)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  564)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300  565)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  566)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  567)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  568)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  569)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300  570) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  571)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  572)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  573)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  574)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  575) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  576)     if( !(repo = open_repository( (const char *)&path[0] )) ) 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)       git_reference_iterator *iter = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  580)       const char *name = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  581)       const char *refs = "refs/heads/*";
05d292b2 (kx 2023-03-24 03:51:10 +0300  582) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  583)       if( git_reference_iterator_glob_new( &iter, repo, refs ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  584)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  585)         close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  586)         return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  587)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  588) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  589)       cgit_ref_names_allocate( &names );
05d292b2 (kx 2023-03-24 03:51:10 +0300  590)       *ref_names = names;
05d292b2 (kx 2023-03-24 03:51:10 +0300  591) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  592)       while( !git_reference_next_name( &name, iter ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  593)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  594)         size_t len = strlen( prefix );
05d292b2 (kx 2023-03-24 03:51:10 +0300  595) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  596)         if( !strncmp( prefix, (char *)&name[11], len ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  597)           cgit_ref_names_add( names, (const char *)&name[11] );
05d292b2 (kx 2023-03-24 03:51:10 +0300  598)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  599)       git_reference_iterator_free( iter );
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)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  603)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  604) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  605)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  606) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  607) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  608) void lookup_tags_by_prefix( struct cgit_ref_names **ref_names, const char *prefix )
05d292b2 (kx 2023-03-24 03:51:10 +0300  609) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  610)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  611)   struct cgit_ref_names *names = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  612) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  613)   if( !ref_names || !prefix || !*prefix ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  614) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  615)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300  616)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300  617)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300  618) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  619)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300  620)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  621)     git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  622)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  623) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  624)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  625)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300  626)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  627)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300  628)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  629)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  630)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300  631) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  632)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  633)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  634)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  635)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  636) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  637)     if( !(repo = open_repository( (const char *)&path[0] )) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  638) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  639)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  640)       git_reference_iterator *iter = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  641)       const char *name = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  642)       const char *refs = "refs/tags/*";
05d292b2 (kx 2023-03-24 03:51:10 +0300  643) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  644)       if( git_reference_iterator_glob_new( &iter, repo, refs ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  645)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  646)         close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  647)         return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  648)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  649) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  650)       cgit_ref_names_allocate( &names );
05d292b2 (kx 2023-03-24 03:51:10 +0300  651)       *ref_names = names;
05d292b2 (kx 2023-03-24 03:51:10 +0300  652) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  653)       while( !git_reference_next_name( &name, iter ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  654)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  655)         size_t len = strlen( prefix );
05d292b2 (kx 2023-03-24 03:51:10 +0300  656) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  657)         if( !strncmp( prefix, (char *)&name[10], len ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  658)           cgit_ref_names_add( names, (const char *)&name[10] );
05d292b2 (kx 2023-03-24 03:51:10 +0300  659)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  660)       git_reference_iterator_free( iter );
05d292b2 (kx 2023-03-24 03:51:10 +0300  661)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  662) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  663)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300  664)   }
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) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  670) /***********************************
05d292b2 (kx 2023-03-24 03:51:10 +0300  671)   List of commits functions:
05d292b2 (kx 2023-03-24 03:51:10 +0300  672)  */
05d292b2 (kx 2023-03-24 03:51:10 +0300  673) struct cgit_hex_commits *cgit_hex_commits_new( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300  674) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  675)   struct cgit_hex_commits *commits = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  676) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  677)   commits = (struct cgit_hex_commits *)xmalloc( sizeof(struct cgit_hex_commits) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  678)   return commits;
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) void cgit_hex_commits_allocate( struct cgit_hex_commits **hex_commits )
05d292b2 (kx 2023-03-24 03:51:10 +0300  682) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  683)   struct cgit_hex_commits *commits = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  684) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  685)   if( !hex_commits ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  686)   commits = (struct cgit_hex_commits *)xmalloc( sizeof(struct cgit_hex_commits) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  687)   *hex_commits = commits;
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) void cgit_hex_commits_add( struct cgit_hex_commits *commits, const char *hex )
05d292b2 (kx 2023-03-24 03:51:10 +0300  691) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  692)   if( !commits ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  693) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  694)   if( !commits->hex )
05d292b2 (kx 2023-03-24 03:51:10 +0300  695)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  696)     commits->hex = (char **)xmalloc( sizeof(char *) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  697)     commits->hex[0] = strdup( hex );
05d292b2 (kx 2023-03-24 03:51:10 +0300  698)     commits->len = (size_t)1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  699)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  700)   else
05d292b2 (kx 2023-03-24 03:51:10 +0300  701)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  702)     commits->hex = (char **)xrealloc( commits->hex, (commits->len + 1) * sizeof(char *) );
05d292b2 (kx 2023-03-24 03:51:10 +0300  703)     commits->hex[commits->len] = strdup( hex );
05d292b2 (kx 2023-03-24 03:51:10 +0300  704)     ++commits->len;
05d292b2 (kx 2023-03-24 03:51:10 +0300  705)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  706) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  707) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  708) void cgit_hex_commits_free( struct cgit_hex_commits *commits )
05d292b2 (kx 2023-03-24 03:51:10 +0300  709) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  710)   if( !commits ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  711) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  712)   if( commits->len && commits->hex )
05d292b2 (kx 2023-03-24 03:51:10 +0300  713)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  714)     size_t i;
05d292b2 (kx 2023-03-24 03:51:10 +0300  715)     for( i = 0; i < commits->len; ++i )
05d292b2 (kx 2023-03-24 03:51:10 +0300  716)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  717)       if( commits->hex[i] )
05d292b2 (kx 2023-03-24 03:51:10 +0300  718)         free( commits->hex[i] );
05d292b2 (kx 2023-03-24 03:51:10 +0300  719)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  720)     free( commits->hex );
05d292b2 (kx 2023-03-24 03:51:10 +0300  721)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  722)   free( commits );
05d292b2 (kx 2023-03-24 03:51:10 +0300  723) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  724) /*
05d292b2 (kx 2023-03-24 03:51:10 +0300  725)   End of List of commits functions.
05d292b2 (kx 2023-03-24 03:51:10 +0300  726)  ***********************************/
05d292b2 (kx 2023-03-24 03:51:10 +0300  727) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  728) void parse_relative_path( char *ref, char *rpath, const char *relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300  729) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  730)   char *s, *p = NULL, *n, *path, *path_info;
05d292b2 (kx 2023-03-24 03:51:10 +0300  731)   int   len = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  732) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  733)   *ref = '\0', *rpath = '\0';
05d292b2 (kx 2023-03-24 03:51:10 +0300  734) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  735)   if( relative_path && *relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300  736)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  737)     path_info = xstrdup( relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300  738)     s = path_info;
05d292b2 (kx 2023-03-24 03:51:10 +0300  739) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  740)     while( *s )
05d292b2 (kx 2023-03-24 03:51:10 +0300  741)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  742)       while( *s &&  *s == '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  743)         ++s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  744)       n = p = s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  745) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  746)       while( *p && *p != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  747)         ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  748)       if( *p )
05d292b2 (kx 2023-03-24 03:51:10 +0300  749)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  750)         *p = '\0'; s = ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  751)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  752)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300  753)         s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  754) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  755)       if( !strcmp( n, "tags" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  756)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  757)         sprintf( ref, "refs/%s/", n );
05d292b2 (kx 2023-03-24 03:51:10 +0300  758)         n = s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  759)         while( *p && *p != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  760)           ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  761)         if( *p )
05d292b2 (kx 2023-03-24 03:51:10 +0300  762)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300  763)           *p = '\0'; s = ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  764)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300  765)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300  766)          s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  767) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  768)         if( n && *n )
05d292b2 (kx 2023-03-24 03:51:10 +0300  769)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300  770)           int   found = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  771)           char  tag[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  772)           char  reminder[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  773)           char *b, *r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  774) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  775)           struct cgit_ref_names *names = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  776) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  777)           sprintf( reminder, "%s", s );
05d292b2 (kx 2023-03-24 03:51:10 +0300  778)           sprintf( tag, "%s", n );
05d292b2 (kx 2023-03-24 03:51:10 +0300  779) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  780)           r = (char *)&reminder[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  781) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  782)           /*********************************
05d292b2 (kx 2023-03-24 03:51:10 +0300  783)             Searching the real name of tag:
05d292b2 (kx 2023-03-24 03:51:10 +0300  784)            */
05d292b2 (kx 2023-03-24 03:51:10 +0300  785)           lookup_tags_by_prefix( &names, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300  786)           while( *r )
05d292b2 (kx 2023-03-24 03:51:10 +0300  787)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300  788)             b = r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  789)             while( *r && *r != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  790)               ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  791)             if( *r )
05d292b2 (kx 2023-03-24 03:51:10 +0300  792)             {
05d292b2 (kx 2023-03-24 03:51:10 +0300  793)               *r = '\0'; ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  794)             }
05d292b2 (kx 2023-03-24 03:51:10 +0300  795) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  796)             if( b && *b )
05d292b2 (kx 2023-03-24 03:51:10 +0300  797)             {
05d292b2 (kx 2023-03-24 03:51:10 +0300  798)               char probe[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  799)               sprintf( probe, "%s/%s", tag, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300  800) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  801)               found = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  802)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300  803)                 size_t i, len = strlen( probe );
05d292b2 (kx 2023-03-24 03:51:10 +0300  804)                 for( i = 0; i < names->len; ++i )
05d292b2 (kx 2023-03-24 03:51:10 +0300  805)                 {
05d292b2 (kx 2023-03-24 03:51:10 +0300  806)                   if( !strncmp( probe, names->name[i], len ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  807)                   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  808)                     ++found;
05d292b2 (kx 2023-03-24 03:51:10 +0300  809)                   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  810)                 }
05d292b2 (kx 2023-03-24 03:51:10 +0300  811)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300  812)               if( found == 1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  813)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300  814)                 strcat( tag, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  815)                 strcat( tag, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300  816)                 break;
05d292b2 (kx 2023-03-24 03:51:10 +0300  817)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300  818)               if( found )
05d292b2 (kx 2023-03-24 03:51:10 +0300  819)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300  820)                 strcat( tag, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  821)                 strcat( tag, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300  822)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300  823)             }
05d292b2 (kx 2023-03-24 03:51:10 +0300  824)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300  825)           cgit_ref_names_free( names );
05d292b2 (kx 2023-03-24 03:51:10 +0300  826) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  827)           if( found )
05d292b2 (kx 2023-03-24 03:51:10 +0300  828)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300  829)             strcat( ref, tag );
05d292b2 (kx 2023-03-24 03:51:10 +0300  830)             p += r - &reminder[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  831)             s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  832)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300  833)           else
05d292b2 (kx 2023-03-24 03:51:10 +0300  834)             strcat( ref, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300  835)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300  836)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300  837)           sprintf( ref, "refs/heads/%s", ctx.repo.trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300  838) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  839)         break;
05d292b2 (kx 2023-03-24 03:51:10 +0300  840)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  841)       else if( !strcmp( n, "branches" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  842)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  843)         sprintf( ref, "refs/heads/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  844) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  845)         n = s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  846)         while( *p && *p != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  847)           ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  848)         if( *p )
05d292b2 (kx 2023-03-24 03:51:10 +0300  849)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300  850)           *p = '\0'; s = ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  851)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300  852)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300  853)          s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  854) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  855)         if( n && *n )
05d292b2 (kx 2023-03-24 03:51:10 +0300  856)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300  857)           int   found = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  858)           char  branch[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  859)           char  reminder[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  860)           char *b, *r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  861) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  862)           struct cgit_ref_names *names = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  863) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  864)           sprintf( reminder, "%s", s );
05d292b2 (kx 2023-03-24 03:51:10 +0300  865)           sprintf( branch, "%s", n );
05d292b2 (kx 2023-03-24 03:51:10 +0300  866) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  867)           r = (char *)&reminder[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  868) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  869)           /************************************
05d292b2 (kx 2023-03-24 03:51:10 +0300  870)             Searching the real name of branch:
05d292b2 (kx 2023-03-24 03:51:10 +0300  871)            */
05d292b2 (kx 2023-03-24 03:51:10 +0300  872)           lookup_branches_by_prefix( &names, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300  873)           while( *r )
05d292b2 (kx 2023-03-24 03:51:10 +0300  874)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300  875)             b = r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  876)             while( *r && *r != '/' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  877)               ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  878)             if( *r )
05d292b2 (kx 2023-03-24 03:51:10 +0300  879)             {
05d292b2 (kx 2023-03-24 03:51:10 +0300  880)               *r = '\0'; ++r;
05d292b2 (kx 2023-03-24 03:51:10 +0300  881)             }
05d292b2 (kx 2023-03-24 03:51:10 +0300  882) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  883)             if( b && *b )
05d292b2 (kx 2023-03-24 03:51:10 +0300  884)             {
05d292b2 (kx 2023-03-24 03:51:10 +0300  885)               char probe[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300  886)               sprintf( probe, "%s/%s", branch, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300  887) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  888)               found = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300  889)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300  890)                 size_t i, len = strlen( probe );
05d292b2 (kx 2023-03-24 03:51:10 +0300  891)                 for( i = 0; i < names->len; ++i )
05d292b2 (kx 2023-03-24 03:51:10 +0300  892)                 {
05d292b2 (kx 2023-03-24 03:51:10 +0300  893)                   if( !strncmp( probe, names->name[i], len ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  894)                   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  895)                     ++found;
05d292b2 (kx 2023-03-24 03:51:10 +0300  896)                   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  897)                 }
05d292b2 (kx 2023-03-24 03:51:10 +0300  898)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300  899)               if( found == 1 )
05d292b2 (kx 2023-03-24 03:51:10 +0300  900)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300  901)                 strcat( branch, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  902)                 strcat( branch, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300  903)                 break;
05d292b2 (kx 2023-03-24 03:51:10 +0300  904)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300  905)               if( found )
05d292b2 (kx 2023-03-24 03:51:10 +0300  906)               {
05d292b2 (kx 2023-03-24 03:51:10 +0300  907)                 strcat( branch, "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300  908)                 strcat( branch, b );
05d292b2 (kx 2023-03-24 03:51:10 +0300  909)               }
05d292b2 (kx 2023-03-24 03:51:10 +0300  910)             }
05d292b2 (kx 2023-03-24 03:51:10 +0300  911)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300  912)           cgit_ref_names_free( names );
05d292b2 (kx 2023-03-24 03:51:10 +0300  913) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  914)           if( found )
05d292b2 (kx 2023-03-24 03:51:10 +0300  915)           {
05d292b2 (kx 2023-03-24 03:51:10 +0300  916)             strcat( ref, branch );
05d292b2 (kx 2023-03-24 03:51:10 +0300  917)             p += r - &reminder[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300  918)             s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  919)           }
05d292b2 (kx 2023-03-24 03:51:10 +0300  920)           else
05d292b2 (kx 2023-03-24 03:51:10 +0300  921)             strcat( ref, n );
05d292b2 (kx 2023-03-24 03:51:10 +0300  922)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300  923)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300  924)           sprintf( ref, "refs/heads/%s", ctx.repo.trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300  925) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  926)         break;
05d292b2 (kx 2023-03-24 03:51:10 +0300  927)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  928)       else if( !strcmp( n, "trunk" ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300  929)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  930)         sprintf( ref, "refs/heads/%s", ctx.repo.trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300  931)         break;
05d292b2 (kx 2023-03-24 03:51:10 +0300  932)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  933)       else
05d292b2 (kx 2023-03-24 03:51:10 +0300  934)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300  935)         /* return '/' */
05d292b2 (kx 2023-03-24 03:51:10 +0300  936)         *--p = '/'; p = n;
05d292b2 (kx 2023-03-24 03:51:10 +0300  937)         sprintf( ref, "refs/heads/%s", ctx.repo.trunk );
05d292b2 (kx 2023-03-24 03:51:10 +0300  938)         break;
05d292b2 (kx 2023-03-24 03:51:10 +0300  939)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300  940)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  941) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  942)     path = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  943) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  944)     if( *path )
05d292b2 (kx 2023-03-24 03:51:10 +0300  945)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  946)       len = (int)strlen( path );
05d292b2 (kx 2023-03-24 03:51:10 +0300  947) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  948)       if( path[len-1] =='/' ) { path[len-1] = '\0'; --len; }
05d292b2 (kx 2023-03-24 03:51:10 +0300  949)       len += 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300  950) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  951)       sprintf( rpath, "%s", path );
05d292b2 (kx 2023-03-24 03:51:10 +0300  952)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  953) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  954)     free( path_info );
05d292b2 (kx 2023-03-24 03:51:10 +0300  955)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  956) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  957) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  958) static void fill_hex_list( struct cgit_hex_commits **hex_commits, char *buf )
05d292b2 (kx 2023-03-24 03:51:10 +0300  959) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  960)   char *s, *p = NULL, *h;
05d292b2 (kx 2023-03-24 03:51:10 +0300  961)   struct cgit_hex_commits *commits = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  962) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  963)   if( !hex_commits || !buf ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  964) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  965)   cgit_hex_commits_allocate( &commits );
05d292b2 (kx 2023-03-24 03:51:10 +0300  966)   *hex_commits = commits;
05d292b2 (kx 2023-03-24 03:51:10 +0300  967) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  968)   s = buf;
05d292b2 (kx 2023-03-24 03:51:10 +0300  969)   while( *s )
05d292b2 (kx 2023-03-24 03:51:10 +0300  970)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300  971)     while( *s &&  *s == '\n' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  972)       ++s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  973)     h = p = s;
05d292b2 (kx 2023-03-24 03:51:10 +0300  974) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  975)     while( *p && *p != '\n' )
05d292b2 (kx 2023-03-24 03:51:10 +0300  976)       ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  977)     if( *p )
05d292b2 (kx 2023-03-24 03:51:10 +0300  978)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300  979)       *p = '\0'; s = ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  980)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300  981)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300  982)       s = p;
05d292b2 (kx 2023-03-24 03:51:10 +0300  983) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  984)     cgit_hex_commits_add( commits, h );
05d292b2 (kx 2023-03-24 03:51:10 +0300  985)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300  986) }
05d292b2 (kx 2023-03-24 03:51:10 +0300  987) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  988) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  989) void cgit_fill_commits_list( struct cgit_hex_commits **hex_commits, int ofs, const char *relative_path, const char *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300  990) {
05d292b2 (kx 2023-03-24 03:51:10 +0300  991)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300  992) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  993)   if( !hex_commits || !relative_path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300  994) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  995)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300  996)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300  997)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300  998) 
05d292b2 (kx 2023-03-24 03:51:10 +0300  999)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1000)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1001)     char ref[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1002)     char rpath[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1003)     int  psize = atoi( ctx.vars.page_size );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1004) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1005)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1006)     char cmd[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1007)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1008)     pid_t p = (pid_t) -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1009)     int   rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1010) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1011)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1012)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1013)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1014)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1015)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1016)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1017)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1018) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1019)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1020)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1021)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1022)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1023) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1024)     parse_relative_path( (char *)&ref[0], (char *)&rpath[0], relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1025) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1026)     /*
05d292b2 (kx 2023-03-24 03:51:10 +0300 1027)       NOTE:
05d292b2 (kx 2023-03-24 03:51:10 +0300 1028)       ====
05d292b2 (kx 2023-03-24 03:51:10 +0300 1029)         The --follow option for blobs is not applicable here because the option --skip=n
05d292b2 (kx 2023-03-24 03:51:10 +0300 1030)         doesn't works when option --follow is defined.
05d292b2 (kx 2023-03-24 03:51:10 +0300 1031) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1032)         In other words we cannot use --follow here:
05d292b2 (kx 2023-03-24 03:51:10 +0300 1033) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1034)         struct cgit_info  info = CGIT_INFO_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1035)         const char *follow = "";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1036) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1037)         if( revision && *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1038)           strncpy( info.revision, revision, GIT_OID_HEXSZ+1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1039)         else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1040)           strncpy( info.revision, ctx.repo.info.revision, GIT_OID_HEXSZ+1 );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1041) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1042)         fill_commit_info( &info, (const char *)&path[0], (const char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1043)         if( info.kind == GIT_OBJECT_BLOB )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1044)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1045)           follow = "--follow";
05d292b2 (kx 2023-03-24 03:51:10 +0300 1046)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1047)      */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1048) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1049)     ++psize;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1050) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1051)     if( revision && *revision )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1052)       snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s log --pretty=format:'%%H' --skip=%d -%d %s -- %s 2>/dev/null", (char *)&path[0], ofs, psize, revision, (char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1053)     else
05d292b2 (kx 2023-03-24 03:51:10 +0300 1054)       snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s log --pretty=format:'%%H' --skip=%d -%d %s -- %s 2>/dev/null", (char *)&path[0], ofs, psize, (char *)&ref[0], (char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1055)     p = sys_exec_command( &buf, cmd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1056)     rc = sys_wait_command( p, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1057)     if( rc != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1058)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1059)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1060)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1061)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1062) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1063)     if( buf.buf[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1064)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1065)       strbuf_trim( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1066) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1067)       fill_hex_list( hex_commits, (char *)&buf.buf[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1068)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1069) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1070)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1071)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1072) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1073)   return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1074) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1075) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1076) git_repository *cgit_open_repository( void )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1077) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1078)   const char     *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1079)   git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1080) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1081)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1082)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1083)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1084) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1085)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1086)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1087)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1088) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1089)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1090)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1091)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1092)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1093)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1094)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1095)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1096) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1097)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1098)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1099)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1100)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1101) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1102)     return open_repository( (const char *)&path[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1103)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1104) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1105)   return repo;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1106) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1107) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1108) git_commit *lookup_commit_by_ref( const char *ref )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1109) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1110)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1111)   git_commit *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1112) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1113)   if( !ref || !*ref ) return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1114) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1115)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1116)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1117)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1118) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1119)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1120)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1121)     git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1122)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1123) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1124)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1125)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1126)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1127)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1128)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1129)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1130)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1131) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1132)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1133)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1134)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1135)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1136) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1137)     if( !(repo = open_repository( (const char *)&path[0] )) ) return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1138)     commit = get_commit_by_ref( repo, ref );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1139)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1140)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1141) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1142)   return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1143) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1144) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1145) git_commit *lookup_commit_by_hex( const char *hex )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1146) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1147)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1148)   git_commit *commit = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1149) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1150)   if( !hex || !*hex ) return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1151) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1152)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1153)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1154)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1155) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1156)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1157)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1158)     git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1159)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1160) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1161)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1162)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1163)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1164)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1165)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1166)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1167)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1168) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1169)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1170)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1171)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1172)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1173) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1174)     if( !(repo = open_repository( (const char *)&path[0] )) ) return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1175)     commit = get_commit_by_hex( repo, hex );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1176)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1177)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1178) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1179)   return commit;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1180) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1181) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1182) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1183) struct print_data {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1184)   struct strbuf *sb;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1185)   int *files;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1186)   int *insertions;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1187)   int *deletions;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1188) };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1189) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1190) static int printer( const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *data )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1191) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1192)   struct print_data *pdata = (struct print_data *)data;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1193) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1194)   (void)delta; (void)hunk;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1195) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1196)   switch( line->origin )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1197)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1198)     case GIT_DIFF_LINE_ADDITION: *pdata->insertions += 1; break;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1199)     case GIT_DIFF_LINE_DELETION: *pdata->deletions  += 1; break;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1200)     case GIT_DIFF_LINE_FILE_HDR: *pdata->files      += 1; break;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1201)     default: break;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1202)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1203) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1204)   if( line->origin == GIT_DIFF_LINE_CONTEXT  ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 1205)       line->origin == GIT_DIFF_LINE_ADDITION ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 1206)       line->origin == GIT_DIFF_LINE_DELETION   )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1207)     strbuf_addch( pdata->sb, line->origin );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1208) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1209)   strbuf_add( pdata->sb, (const void *)line->content, (size_t)line->content_len );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1210) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1211)   return 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1212) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1213) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1214) void cgit_fill_diff_with_parent( struct strbuf *sb, char *parent_hex, size_t parent_len, int *files, int *insertions, int *deletions, const char *hex )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1215) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1216)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1217) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1218)   git_commit *commit = NULL, *parent = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1219)   git_tree   *commit_tree = NULL, *parent_tree = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1220)   git_diff   *diff = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1221) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1222)   struct print_data  data = { .sb = NULL, .files = NULL, .insertions = NULL, .deletions = NULL };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1223) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1224)   if( !parent_hex || !files || !insertions || !deletions || !hex || !*hex ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1225)   if( parent_len != GIT_OID_HEXSZ+1 ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1226) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1227)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1228)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1229)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1230) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1231)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1232)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1233)     git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1234)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1235) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1236)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1237)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1238)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1239)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1240)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1241)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1242)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1243) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1244)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1245)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1246)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1247)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1248) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1249)     if( !(repo = open_repository( (const char *)&path[0] )) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1250) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1251)     commit = get_commit_by_hex( repo, hex );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1252)     if( git_commit_parent( &parent, commit, 0 ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1253)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1254)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1255)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1256)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1257)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1258)     if( git_oid_tostr( parent_hex, GIT_OID_HEXSZ+1, git_commit_id( parent ) ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1259)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1260)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1261)       git_commit_free( parent );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1262)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1263)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1264)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1265) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1266)     if( git_commit_tree( &commit_tree, commit ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1267)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1268)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1269)       git_commit_free( parent );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1270)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1271)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1272)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1273)     if( git_commit_tree( &parent_tree, parent ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1274)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1275)       git_tree_free( commit_tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1276)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1277)       git_commit_free( parent );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1278)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1279)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1280)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1281)     if( git_diff_tree_to_tree( &diff, repo, parent_tree, commit_tree, NULL ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1282)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1283)       git_tree_free( commit_tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1284)       git_tree_free( parent_tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1285)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1286)       git_commit_free( parent );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1287)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1288)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1289)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1290) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1291) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1292)     *files = 0, *insertions = 0, *deletions = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1293) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1294)     data.sb         = sb;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1295)     data.files      = files;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1296)     data.insertions = insertions;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1297)     data.deletions  = deletions;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1298) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1299)     git_diff_print( diff, GIT_DIFF_FORMAT_PATCH, printer, &data );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1300) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1301)     *files = *data.files, *insertions = *data.insertions, *deletions = *data.deletions;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1302) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1303)     git_diff_free( diff );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1304)     git_tree_free( commit_tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1305)     git_tree_free( parent_tree );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1306)     git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1307)     git_commit_free( parent );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1308) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1309)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1310)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1311) }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1312) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1313) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1314) void cgit_diff_with_parent( struct strbuf *sb, char *parent_hex, size_t parent_len, int *files, int *insertions, int *deletions, const char *hex, const char *relative_path )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1315) {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1316)   const char *name = NULL, *git_root = NULL, *repo_root = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1317) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1318)   git_commit *commit = NULL, *parent = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1319) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1320)   if( !parent_hex || !files || !insertions || !deletions || !hex || !*hex || !relative_path || !*relative_path ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1321)   if( parent_len != GIT_OID_HEXSZ+1 ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1322) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1323)   name      = ctx.repo.name;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1324)   git_root  = ctx.repo.git_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1325)   repo_root = ctx.repo.repo_root;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1326) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1327)   *files = 0, *insertions = 0, *deletions = 0;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1328) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1329)   if( name && git_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1330)   {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1331)     char ref[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1332)     char rpath[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1333) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1334)     git_repository *repo = NULL;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1335)     char path[PATH_MAX] = { 0 };
05d292b2 (kx 2023-03-24 03:51:10 +0300 1336)     char cmd[PATH_MAX];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1337)     struct strbuf buf = STRBUF_INIT;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1338)     pid_t p = (pid_t) -1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1339)     int   rc;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1340) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1341)     sprintf( (char *)&path[0], "%s/", git_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1342)     if( repo_root && *repo_root )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1343)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1344)       strcat( (char *)&path[0], repo_root );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1345)       strcat( (char *)&path[0], "/" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1346)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1347)     strcat( (char *)&path[0], name );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1348) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1349)     if( !is_bare( (char *)&path[0] ) )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1350)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1351)       strcat( (char *)&path[0], "/.git" );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1352)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1353) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1354)     if( !(repo = open_repository( (const char *)&path[0] )) ) return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1355) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1356)     commit = get_commit_by_hex( repo, hex );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1357)     if( git_commit_parent( &parent, commit, 0 ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1358)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1359)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1360)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1361)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1362)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1363)     if( git_oid_tostr( parent_hex, GIT_OID_HEXSZ+1, git_commit_id( parent ) ) < 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1364)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1365)       git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1366)       git_commit_free( parent );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1367)       close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1368)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1369)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1370) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1371)     git_commit_free( commit );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1372)     git_commit_free( parent );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1373)     close_repository( repo );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1374) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1375)     /* now we have two revisions */
05d292b2 (kx 2023-03-24 03:51:10 +0300 1376)     parse_relative_path( (char *)&ref[0], (char *)&rpath[0], relative_path );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1377) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1378)     snprintf( (char *)&cmd[0], 1024, "git --git-dir=%s diff %s %s -- %s 2>/dev/null", (char *)&path[0], parent_hex, hex, (char *)&rpath[0] );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1379)     p = sys_exec_command( &buf, cmd );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1380)     rc = sys_wait_command( p, NULL );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1381)     if( rc != 0 )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1382)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1383)       strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1384)       return;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1385)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1386) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1387)     if( buf.buf[0] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1388)     {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1389)       char *p = (char *)&buf.buf[0];
05d292b2 (kx 2023-03-24 03:51:10 +0300 1390) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1391)       while( *p )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1392)       {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1393)         if( *p == '\n' && p[1] && p[2] && p[3] )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1394)         {
05d292b2 (kx 2023-03-24 03:51:10 +0300 1395)           if( (p[1] == '+' && p[2] == '+' && p[3] == '+') ||
05d292b2 (kx 2023-03-24 03:51:10 +0300 1396)               (p[1] == '-' && p[2] == '-' && p[3] == '-')   )
05d292b2 (kx 2023-03-24 03:51:10 +0300 1397)             *files += 1;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1398)           if( p[1] == '+' && p[2] != '+' && p[3] != '+' ) { ++p; *insertions += 1; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1399)           if( p[1] == '-' && p[2] != '-' && p[3] != '-' ) { ++p; *deletions  += 1; }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1400)         }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1401)         ++p;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1402)       }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1403)       *files /= 2;
05d292b2 (kx 2023-03-24 03:51:10 +0300 1404) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1405)       strbuf_addbuf( sb, (const struct strbuf *)&buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1406)     }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1407) 
05d292b2 (kx 2023-03-24 03:51:10 +0300 1408)     strbuf_release( &buf );
05d292b2 (kx 2023-03-24 03:51:10 +0300 1409)   }
05d292b2 (kx 2023-03-24 03:51:10 +0300 1410) }