cSvn-UI for SVN Repositories

cGit-UI – is a web interface for Subversion (SVN) Repositories. cSvn CGI script is writen in C and therefore it's fast enough

6 Commits   0 Branches   2 Tags
author: kx <kx@radix.pro> 2023-04-12 19:21:06 +0300 committer: kx <kx@radix.pro> 2023-04-12 19:21:06 +0300 commit: c7693c71799633467d154afe65f9b4810cec42f5 parent: c8b2593c941778dcfa307badf981160e19d2932b
Commit Summary:
Added repo-root variable for repositories which placed in subdirectory relative svnserve root
Diffstat:
1 file changed, 90 insertions, 30 deletions
diff --git a/csvncgi/ctx.c b/csvncgi/ctx.c
index e3405c4..e7e4e2a 100644
--- a/csvncgi/ctx.c
+++ b/csvncgi/ctx.c
@@ -181,6 +181,7 @@ void csvn_prepare_context( void )
 
   ctx.repo.name = NULL;
   ctx.repo.info = CSVN_INFO_INIT;
+  ctx.repo.repo_root = NULL;
   ctx.repo.relative_path = NULL;
   ctx.repo.relative_info = CSVN_INFO_INIT;
   ctx.repo.relative_html = NULL;
@@ -408,13 +409,19 @@ static void ctx_page_size_from_repo( struct repo *repo )
 
 static void ctx_repo_dirs_from_global( void )
 {
-  struct variable  trunk     = { (unsigned char *)"trunk",    { 0 }, DT_PATH };
-  struct variable  branches  = { (unsigned char *)"branches", { 0 }, DT_PATH };
-  struct variable  tags      = { (unsigned char *)"tags",     { 0 }, DT_PATH };
+  struct variable  repo_root = { (unsigned char *)"repo-root", { 0 }, DT_PATH };
+  struct variable  trunk     = { (unsigned char *)"trunk",     { 0 }, DT_PATH };
+  struct variable  branches  = { (unsigned char *)"branches",  { 0 }, DT_PATH };
+  struct variable  tags      = { (unsigned char *)"tags",      { 0 }, DT_PATH };
   struct variable  ro_prefix = { (unsigned char *)"checkout-prefix-readonly", { 0 }, DT_PATH };
   struct variable  rw_prefix = { (unsigned char *)"checkout-prefix",          { 0 }, DT_PATH };
   struct variable *var = NULL;
 
+  var = lookup_global( lookup_global_section( config ), &repo_root );
+  if( var )
+  {
+    ctx.repo.repo_root = (const char *)var->_v.vptr;
+  }
   var = lookup_global( lookup_global_section( config ), &trunk );
   if( var )
   {
@@ -671,15 +678,21 @@ static void ctx_promo_vars_from_global( void )
 
 static void ctx_repo_dirs_from_repo( struct repo *repo )
 {
-  struct variable  trunk     = { (unsigned char *)"trunk",    { 0 }, DT_PATH };
-  struct variable  branches  = { (unsigned char *)"branches", { 0 }, DT_PATH };
-  struct variable  tags      = { (unsigned char *)"tags",     { 0 }, DT_PATH };
+  struct variable  repo_root = { (unsigned char *)"repo-root", { 0 }, DT_PATH };
+  struct variable  trunk     = { (unsigned char *)"trunk",     { 0 }, DT_PATH };
+  struct variable  branches  = { (unsigned char *)"branches",  { 0 }, DT_PATH };
+  struct variable  tags      = { (unsigned char *)"tags",      { 0 }, DT_PATH };
   struct variable  ro_prefix = { (unsigned char *)"checkout-prefix-readonly", { 0 }, DT_PATH };
   struct variable  rw_prefix = { (unsigned char *)"checkout-prefix",          { 0 }, DT_PATH };
   struct variable *var = NULL;
 
   if( !repo ) return;
 
+  var = lookup( repo, &repo_root );
+  if( var )
+  {
+    ctx.repo.repo_root = (const char *)var->_v.vptr;
+  }
   var = lookup( repo, &trunk );
   if( var )
   {
@@ -1165,45 +1178,92 @@ static void ctx_footer_from_repo( struct repo *repo )
 }
 
 
-static void ctx_repo_name( void )
+static char name[PATH_MAX] = { 0 };
+static char repo_root[PATH_MAX] = { 0 };
+static char relative_path[PATH_MAX] = { 0 };
+
+static char try[PATH_MAX] = { 0 };
+
+static struct repo *ctx_repo_name( void )
 {
-  char *p, *path, *rpath, *name, *rname, *path_info;
+  struct repo *repo = NULL;
+  char *s, *p = NULL, *n, *path, *path_info;
   int   len = 0;
 
   if( strcmp( "/", ctx.env.path_info ) )
   {
     path_info = xstrdup( ctx.env.path_info );
-    name = path_info;
+    s = path_info;
 
-    while( *name && is_dir_sep( *name ) )
-      ++name;
-    p = name;
-    while( *p && !is_dir_sep( *p ) )
-      ++p;
+    while( *s )
+    {
+      while( *s && is_dir_sep( *s ) )
+        ++s;
+      n = p = s;
 
-    if( *p ) { *p = '\0'; path = ++p; }
-    else
-      path = p;
+      while( *p && !is_dir_sep( *p ) )
+        ++p;
+      if( *p )
+      {
+        *p = '\0'; s = ++p;
 
-    len = (int)strlen( name ) + 1;
-    rname = (char *)__sbrk( len );
-    memcpy( (void *)rname, (const void *)name, len );
-    ctx.repo.name = (const char *)rname;
+        /****************************************************************
+          The repo name can be given as a relative path in the git-root:
+         */
+        if( repo_root[0] )
+        {
+          sprintf( try, "%s", repo_root );
+          strcat( try, "/" );
+          strcat( try, n );
+        }
+        else
+        {
+          sprintf( try, "%s", n );
+        }
+
+        if( (repo = lookup_repo( config, try )) )
+        {
+          sprintf( name, "%s", try );
+          {
+            char *rr = strstr( repo_root, try );
+            if( rr )
+              *rr = '\0';
+            else
+              repo_root[0] = '\0';
+          }
+          break;
+        }
+        else
+        {
+          if( repo_root[0] )
+            strcat( repo_root, "/" );
+          strcat( repo_root, n );
+        }
+      }
+      else
+        s = p;
+    }
+
+    ctx.repo.name = (const char *)&name[0];
+    ctx.repo.repo_root = (const char *)&repo_root[0];
+
+    path = p;
 
     if( *path )
     {
       len = (int)strlen( path );
 
-      if( is_dir_sep( path[len-1] ) ) { path[len-1] = '\0'; --len; }
+      if( path[len-1] =='/' ) { path[len-1] = '\0'; --len; }
       len += 1;
 
-      rpath = (char *)__sbrk( len );
-      memcpy( (void *)rpath, (const void *)path, len );
-      ctx.repo.relative_path = (const char *)rpath;
+      sprintf( relative_path, "%s", path );
+      ctx.repo.relative_path = (const char *)&relative_path[0];
     }
 
     free( path_info );
   }
+
+  return repo;
 }
 
 
@@ -1342,9 +1402,12 @@ static void ctx_relative_html( void )
   }
   else if( !strcmp( ctx.vars.page_type, ptype_repo ) )
   {
-    if( ctx.repo.name && *ctx.repo.name && ctx.repo.info.kind != KIND_UNKNOWN )
+    if( ctx.repo.name && *ctx.repo.name && ctx.repo.info.kind != KIND_UNKNOWN  )
     {
-      strbuf_addf( &buf, "<a class='base' href='/%s/'>%s</a>/", ctx.repo.name, ctx.repo.name );
+      if( ctx.repo.repo_root && *ctx.repo.repo_root )
+        strbuf_addf( &buf, "<a class='base' href='/%s/%s/'>%s/%s</a>/", ctx.repo.repo_root, ctx.repo.name, ctx.repo.repo_root, ctx.repo.name );
+      else
+        strbuf_addf( &buf, "<a class='base' href='/%s/'>%s</a>/", ctx.repo.name, ctx.repo.name );
     }
     if( ctx.repo.relative_path && *ctx.repo.relative_path && ctx.repo.relative_info.kind != KIND_UNKNOWN )
     {
@@ -1524,8 +1587,7 @@ void csvn_parse_query( void )
     {
       struct repo *repo = NULL;
 
-      ctx_repo_name();
-      repo = lookup_repo( config, ctx.repo.name );
+      repo = ctx_repo_name();
       if( repo )
       {
         ctx_page_size_from_repo( repo );
@@ -1562,7 +1624,11 @@ void csvn_parse_query( void )
           struct strbuf  buf = STRBUF_INIT;
           char  *stmsg = NULL;
 
-          strbuf_addf( &buf, "Subversion Repository '%s' not found.", ctx.repo.name );
+          /**************************************************************************
+            We slipped to the end of PATH_INFO when we were looking for a repository
+            and now we printout the repo-root:
+           */
+          strbuf_addf( &buf, "Subversion Repository '%s' not found.", ctx.repo.repo_root );
           stmsg = (char *)__sbrk( (int)buf.len + 1 );
           memcpy( (void *)stmsg, (const void *)buf.buf, buf.len + 1 );
           strbuf_release( &buf );