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, 150 insertions, 26 deletions
diff --git a/csvncgi/ui-tree.c b/csvncgi/ui-tree.c
index bc46535..007abc2 100644
--- a/csvncgi/ui-tree.c
+++ b/csvncgi/ui-tree.c
@@ -147,7 +147,8 @@ static struct dlist *tree_lines_sort_bytag( struct dlist *lines )
 static const char *is_file_executable( const char *relative_path, const char *name, int revision )
 {
   const char *co_prefix = ctx.repo.checkout_ro_prefix;
-  const char *repo_path = ctx.repo.name;
+  const char *repo_name = ctx.repo.name;
+  const char *repo_root = ctx.repo.repo_root;
   const char *ret  = "";
   char *path = NULL;
 
@@ -167,19 +168,27 @@ static const char *is_file_executable( const char *relative_path, const char *na
 
   if( co_prefix )
   {
-    char cmd[1024];
+    char repo_path[PATH_MAX] = { 0 };
+    char cmd[PATH_MAX];
     struct strbuf buf = STRBUF_INIT;
     pid_t p = (pid_t) -1;
     int   rc;
 
+    if( repo_root && *repo_root )
+    {
+      strcat( (char *)&repo_path[0], repo_root );
+      strcat( (char *)&repo_path[0], "/" );
+    }
+    strcat( (char *)&repo_path[0], repo_name );
+
     if( revision )
       snprintf( (char *)&cmd[0], 1024,
                 "svn propget svn:executable --revision %d %s/%s%s/%s 2>/dev/null",
-                revision, co_prefix, repo_path, path, name );
+                revision, co_prefix, (char *)&repo_path[0], path, name );
     else
       snprintf( (char *)&cmd[0], 1024,
                 "svn propget svn:executable %s/%s%s/%s 2>/dev/null",
-                co_prefix, repo_path, path, name );
+                co_prefix, (char *)&repo_path[0], path, name );
     p = sys_exec_command( &buf, cmd );
     rc = sys_wait_command( p, NULL );
     if( rc != 0 )
@@ -432,9 +441,27 @@ static void dlist_csvn_tree( struct strbuf *sb, const char *relative_path, int r
 
         strbuf_addf( sb, "                <div class=\"row\">\n" );
         if( ctx.env.query_string && *ctx.env.query_string )
-          strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/?%s\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, path, line->name, ctx.env.query_string, line->name );
+        {
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/?%s\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, ctx.env.query_string, line->name );
+          }
+          else
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/?%s\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, path, line->name, ctx.env.query_string, line->name );
+          }
+        }
         else
-          strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, path, line->name, line->name );
+        {
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->name );
+          }
+          else
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/\"><div class=\"tree-path dir\">%s/</div></a></div>\n", ctx.repo.name, path, line->name, line->name );
+          }
+        }
         strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">4096</div></div>\n" );
         strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\">%s</div></div>\n", line->revision );
         if( time != -1 )
@@ -451,13 +478,29 @@ static void dlist_csvn_tree( struct strbuf *sb, const char *relative_path, int r
         strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
         if( query_string && *query_string )
         {
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision, query_string );
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
+          }
+          else
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision, query_string );
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s&%s\">diff</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
+          }
         }
         else
         {
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.name, path, line->name, line->revision );
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
+          }
+          else
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s\">diff</a>\n", ctx.repo.name, path, line->name, line->revision );
+          }
         }
         strbuf_addf( sb, "                    </div>\n" );
         strbuf_addf( sb, "                  </div>\n" );
@@ -492,9 +535,27 @@ static void dlist_csvn_tree( struct strbuf *sb, const char *relative_path, int r
 
         strbuf_addf( sb, "                <div class=\"row\">\n" );
         if( ctx.env.query_string && *ctx.env.query_string )
-          strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/?%s\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.name, path, line->name, ctx.env.query_string, exec, line->name );
+        {
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/?%s\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, ctx.env.query_string, exec, line->name );
+          }
+          else
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/?%s\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.name, path, line->name, ctx.env.query_string, exec, line->name );
+          }
+        }
         else
-          strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.name, path, line->name, exec, line->name );
+        {
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s/%s%s/%s/\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, exec, line->name );
+          }
+          else
+          {
+            strbuf_addf( sb, "                  <div class=\"col-path\"><a href=\"/%s%s/%s/\"><div class=\"tree-path file%s\">%s</div></a></div>\n", ctx.repo.name, path, line->name, exec, line->name );
+          }
+        }
         strbuf_addf( sb, "                  <div class=\"col-size\"><div onclick=\"trunc(this)\" class=\"tree-size trunc\">%s</div></div>\n", line->size );
         strbuf_addf( sb, "                  <div class=\"col-rev\"><div onclick=\"trunc(this)\" class=\"tree-rev trunc\">%s</div></div>\n", line->revision );
         if( time != -1 )
@@ -511,15 +572,33 @@ static void dlist_csvn_tree( struct strbuf *sb, const char *relative_path, int r
         strbuf_addf( sb, "                    <div onclick=\"trunc(this)\" class=\"tree-links trunc\">\n" );
         if( query_string && *query_string )
         {
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision, query_string );
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s&%s\">diff &nbsp;</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=blame&rev=%s&%s\">blame</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s&%s\">diff &nbsp;</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=blame&rev=%s&%s\">blame</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision, query_string );
+          }
+          else
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s&%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision, query_string );
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s&%s\">diff &nbsp;</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=blame&rev=%s&%s\">blame</a>\n", ctx.repo.name, path, line->name, line->revision, query_string );
+          }
         }
         else
         {
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s\">diff</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
-          strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=blame&rev=%s\">blame</a>\n", ctx.repo.name, path, line->name, line->revision );
+          if( ctx.repo.repo_root && *ctx.repo.repo_root )
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=diff&rev=%s\">diff</a> &nbsp;\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
+            strbuf_addf( sb, "                      <a href=\"/%s/%s%s/%s/?op=blame&rev=%s\">blame</a>\n", ctx.repo.repo_root, ctx.repo.name, path, line->name, line->revision );
+          }
+          else
+          {
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=log&rev=%s\">log</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=diff&rev=%s\">diff</a> &nbsp;\n", ctx.repo.name, path, line->name, line->revision );
+            strbuf_addf( sb, "                      <a href=\"/%s%s/%s/?op=blame&rev=%s\">blame</a>\n", ctx.repo.name, path, line->name, line->revision );
+          }
         }
         strbuf_addf( sb, "                    </div>\n" );
         strbuf_addf( sb, "                  </div>\n" );
@@ -539,7 +618,8 @@ static void dlist_csvn_tree( struct strbuf *sb, const char *relative_path, int r
 static void csvn_print_tree( struct strbuf *sb, const char *relative_path, int revision )
 {
   const char *co_prefix = ctx.repo.checkout_ro_prefix;
-  const char *repo_path = ctx.repo.name;
+  const char *name      = ctx.repo.name;
+  const char *repo_root = ctx.repo.repo_root;
   char *path = NULL;
 
   if( !sb ) return;
@@ -558,19 +638,27 @@ static void csvn_print_tree( struct strbuf *sb, const char *relative_path, int r
 
   if( co_prefix )
   {
-    char cmd[1024];
+    char repo_path[PATH_MAX] = { 0 };
+    char cmd[PATH_MAX];
     struct strbuf buf = STRBUF_INIT;
     pid_t p = (pid_t) -1;
     int   rc;
 
+    if( repo_root && *repo_root )
+    {
+      strcat( (char *)&repo_path[0], repo_root );
+      strcat( (char *)&repo_path[0], "/" );
+    }
+    strcat( (char *)&repo_path[0], name );
+
     if( revision )
       snprintf( (char *)&cmd[0], 1024,
                 "svn list --revision %d --xml %s/%s%s 2>/dev/null",
-                revision, co_prefix, repo_path, path );
+                revision, co_prefix, (char *)&repo_path[0], path );
     else
       snprintf( (char *)&cmd[0], 1024,
                 "svn list --xml %s/%s%s 2>/dev/null",
-                co_prefix, repo_path, path );
+                co_prefix, (char *)&repo_path[0], path );
     p = sys_exec_command( &buf, cmd );
     rc = sys_wait_command( p, NULL );
     if( rc != 0 )
@@ -615,9 +703,27 @@ static void csvn_print_checkout_urls( struct strbuf *sb, const char *relative_pa
   strbuf_addf( sb, "                      <div class=\"checkout-perms\">ro:</div>\n" );
 
   if( revision )
-    strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s%s</div>\n", revision, ctx.repo.checkout_ro_prefix, ctx.repo.name, path );
+  {
+    if( ctx.repo.repo_root && *ctx.repo.repo_root )
+    {
+      strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s/%s%s</div>\n", revision, ctx.repo.checkout_ro_prefix, ctx.repo.repo_root, ctx.repo.name, path );
+    }
+    else
+    {
+      strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s%s</div>\n", revision, ctx.repo.checkout_ro_prefix, ctx.repo.name, path );
+    }
+  }
   else
-    strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s%s</div>\n", ctx.repo.checkout_ro_prefix, ctx.repo.name, path );
+  {
+    if( ctx.repo.repo_root && *ctx.repo.repo_root )
+    {
+      strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s/%s%s</div>\n", ctx.repo.checkout_ro_prefix, ctx.repo.repo_root, ctx.repo.name, path );
+    }
+    else
+    {
+      strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s%s</div>\n", ctx.repo.checkout_ro_prefix, ctx.repo.name, path );
+    }
+  }
 
   strbuf_addf( sb, "                    </div>\n" );
   if( ctx.repo.checkout_prefix && *ctx.repo.checkout_prefix )
@@ -626,9 +732,27 @@ static void csvn_print_checkout_urls( struct strbuf *sb, const char *relative_pa
     strbuf_addf( sb, "                      <div class=\"checkout-perms\">rw:</div>\n" );
 
     if( revision )
-      strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s%s</div>\n", revision, ctx.repo.checkout_prefix, ctx.repo.name, path );
+    {
+      if( ctx.repo.repo_root && *ctx.repo.repo_root )
+      {
+        strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s/%s%s</div>\n", revision, ctx.repo.checkout_prefix, ctx.repo.repo_root, ctx.repo.name, path );
+      }
+      else
+      {
+        strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout --revision %d %s/%s%s</div>\n", revision, ctx.repo.checkout_prefix, ctx.repo.name, path );
+      }
+    }
     else
-      strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s%s</div>\n", ctx.repo.checkout_prefix, ctx.repo.name, path );
+    {
+      if( ctx.repo.repo_root && *ctx.repo.repo_root )
+      {
+        strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s/%s%s</div>\n", ctx.repo.checkout_prefix, ctx.repo.repo_root, ctx.repo.name, path );
+      }
+      else
+      {
+        strbuf_addf( sb, "                      <div class=\"checkout-url\">svn checkout %s/%s%s</div>\n", ctx.repo.checkout_prefix, ctx.repo.name, path );
+      }
+    }
 
     strbuf_addf( sb, "                    </div>\n" );
   }