svn commit: r1932716 - subversion/trunk/subversion/svnbrowse

[email protected]
Newsgroups gmane.comp.version-control.subversion.svn
Message-ID <177507109129.1815125.11876289053765727072@svn03-he-fi>
Author: rinrab
Date: Wed Apr  1 19:18:11 2026
New Revision: 1932716

Log:
svnbrowse: Add an abstraction for 'browser state' which is a structure that can
hold all information needed to display the contents of a path in the browser.
When leaving a state, the previous one is droped.

* subversion/svnbrowse/svnbrowse.c
  (svn_browse__state_t): New struct.
  (svn_browse__ctx_t): Store pointer to the current state, removing fields like
   list, selection and relpath from the ctx 
  (list_cb): Treat baton as svn_browse__state_t.
  (state_create): New function that retrieves 'svn list' data and loads it into
   a newly created instance of svn_browse__state_t.
  (enter_path): Use state_create() and properly destroy previous state.
  (ui_draw, sub_main): Use ctx->current to access the state.

Modified:
   subversion/trunk/subversion/svnbrowse/svnbrowse.c

Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.c	Wed Apr  1 18:45:04 2026	(r1932715)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.c	Wed Apr  1 19:18:11 2026	(r1932716)
@@ -42,16 +42,30 @@ typedef struct svn_browse__item_t {
   const svn_dirent_t *dirent;
 } svn_browse__item_t;
 
+/* a state of a single directory */
+typedef struct svn_browse__state_t {
+  /* information about this node */
+  const char *relpath;
+  svn_opt_revision_t revision;
+
+  /* stores the list of nodes in this state; an array of svn_browse__item_t */
+  apr_array_header_t *list;
+
+  /* the index of hovered item */
+  int selection;
+
+  /* a pool where the structure is allocated */
+  apr_pool_t *pool;
+} svn_browse__state_t;
+
 typedef struct svn_browse__ctx_t {
   const char *root;
-  const char *relpath;
   svn_opt_revision_t revision;
 
   svn_client_ctx_t *client;
 
-  apr_array_header_t *list;
-  int selection;
-  apr_pool_t *list_pool;
+  svn_browse__state_t *current;
+  apr_pool_t *pool;
 } svn_browse__ctx_t;
 
 static svn_error_t *
@@ -81,26 +95,51 @@ list_cb(void *baton,
         const char *external_target,
         apr_pool_t *scratch_pool)
 {
-  svn_browse__ctx_t *ctx = baton;
-  svn_browse__item_t *item = apr_pcalloc(ctx->list_pool, sizeof(*item));
-  item->relpath = apr_pstrdup(ctx->list_pool, path);
-  item->dirent = svn_dirent_dup(dirent, ctx->list_pool);
-  APR_ARRAY_PUSH(ctx->list, svn_browse__item_t *) = item;
+  svn_browse__state_t *state = baton;
+  svn_browse__item_t *item = apr_pcalloc(state->pool, sizeof(*item));
+  item->relpath = apr_pstrdup(state->pool, path);
+  item->dirent = svn_dirent_dup(dirent, state->pool);
+  APR_ARRAY_PUSH(state->list, svn_browse__item_t *) = item;
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
-enter_path(svn_browse__ctx_t *ctx, const char *relpath, apr_pool_t *pool)
+state_create(svn_browse__state_t **state_p,
+             svn_browse__ctx_t *ctx,
+             const char *relpath,
+             apr_pool_t *result_pool,
+             apr_pool_t *scratch_pool)
 {
-  const char *abspath = svn_path_url_add_component2(ctx->root, relpath, pool);
-  ctx->relpath = apr_pstrdup(pool, relpath);
-
-  ctx->list = apr_array_make(pool, 0, sizeof(svn_browse__item_t *));
-  ctx->selection = 0;
+  svn_browse__state_t *state = apr_pcalloc(result_pool, sizeof(*state));
+  const char *abspath = svn_path_url_add_component2(ctx->root, relpath,
+                                                    scratch_pool);
+
+  state->relpath = apr_pstrdup(result_pool, relpath);
+  state->revision = state->revision;
+  state->list = apr_array_make(result_pool, 0, sizeof(svn_browse__item_t *));
+  state->selection = 0;
+  state->pool = result_pool;
 
   SVN_ERR(svn_client_list4(abspath, &ctx->revision, &ctx->revision, NULL,
                            svn_depth_immediates, SVN_DIRENT_ALL, TRUE, TRUE,
-                           list_cb, ctx, ctx->client, pool));
+                           list_cb, state, ctx->client, scratch_pool));
+
+  *state_p = state;
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+enter_path(svn_browse__ctx_t *ctx, const char *relpath,
+           apr_pool_t *scratch_pool)
+{
+  svn_browse__state_t *newstate;
+  apr_pool_t *state_pool = svn_pool_create(ctx->pool);
+
+  SVN_ERR(state_create(&newstate, ctx, relpath, state_pool, scratch_pool));
+
+  /* switch to the next state and nuke the previous one */
+  apr_pool_destroy(ctx->current->pool);
+  ctx->current = newstate;
 
   return SVN_NO_ERROR;
 }
@@ -109,17 +148,18 @@ static void
 ui_draw(svn_browse__ctx_t *ctx, apr_pool_t *pool)
 {
   int i;
-  const char *abspath = svn_path_url_add_component2(ctx->root, ctx->relpath,
+  const char *abspath = svn_path_url_add_component2(ctx->root,
+                                                    ctx->current->relpath,
                                                     pool);
 
   mvprintw(0, 4, "Browsing: %s", abspath);
 
-  for (i = 0; i < ctx->list->nelts; i++)
+  for (i = 0; i < ctx->current->list->nelts; i++)
     {
-      svn_browse__item_t *item = APR_ARRAY_IDX(ctx->list, i,
+      svn_browse__item_t *item = APR_ARRAY_IDX(ctx->current->list, i,
                                                svn_browse__item_t *);
 
-      if (i == ctx->selection)
+      if (i == ctx->current->selection)
         standout();
 
       if (i == 0)
@@ -136,7 +176,7 @@ ui_draw(svn_browse__ctx_t *ctx, apr_pool
                item->dirent->created_rev,
                item->dirent->last_author);
 
-      if (i == ctx->selection)
+      if (i == ctx->current->selection)
         standend();
     }
 }
@@ -153,10 +193,10 @@ sub_main(int *code, int argc, char *argv
 
   SVN_ERR(svn_uri_canonicalize_safe(&ctx.root, NULL, argv[1], pool, pool));
   ctx.revision.kind = svn_opt_revision_head;
-  ctx.list_pool = pool;
+  ctx.pool = pool;
 
   SVN_ERR(init_client(&ctx, pool));
-  SVN_ERR(enter_path(&ctx, "", pool));
+  SVN_ERR(state_create(&ctx.current, &ctx, "", svn_pool_create(pool), pool));
 
   /* init the display */
   initscr();
@@ -192,23 +232,24 @@ sub_main(int *code, int argc, char *argv
         {
           case KEY_UP:
           case 'k':
-            ctx.selection--;
+            ctx.current->selection--;
             break;
           case KEY_DOWN:
           case 'j':
-            ctx.selection++;
+            ctx.current->selection++;
             break;
           case '\n':
           case '\r':
-            item = APR_ARRAY_IDX(ctx.list, ctx.selection,
+            item = APR_ARRAY_IDX(ctx.current->list, ctx.current->selection,
                                  svn_browse__item_t *);
-            new_url = svn_relpath_join(ctx.relpath, item->relpath, iterpool);
+            new_url = svn_relpath_join(ctx.current->relpath, item->relpath,
+                                       iterpool);
             SVN_ERR(enter_path(&ctx, new_url, iterpool));
             break;
           case KEY_BACKSPACE:
           case '-':
           case 'u':
-            new_url = svn_relpath_dirname(ctx.relpath, iterpool);
+            new_url = svn_relpath_dirname(ctx.current->relpath, iterpool);
             SVN_ERR(enter_path(&ctx, new_url, iterpool));
             break;
           /* TODO: quit via escape. some say just check for 27, but it I think it's
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.