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

[email protected]
Newsgroups gmane.comp.version-control.subversion.svn
Message-ID <177514506789.2210993.1450863490306121909@svn03-he-fi>
Author: rinrab
Date: Thu Apr  2 15:51:07 2026
New Revision: 1932742

Log:
svnbrowse: Use libsvn_ra API directly to query directories. Do so for improved
performance (by reusing the same session) and more control of what is
actually transmitted over the wire.

* subversion/svnbrowse/svnbrowse.c
  (includes): Add svn_ra.h.
  (svn_browse__state_t): Change abspath to relpath and the revision is now just
   a number. Although most of the logic just ignore it for now.
  (svn_browse__model_t): Store ra_session and change how we store revision.
  (list_cb): Implement svn_ra_dirent_receiver_t instead of
   svn_client_list_func2_t. Take basename of relpath when processing it.
  (state_create): Change the API used to back the operation.
  (enter_path): Update state_create() invokation and change abspath back to
   relpath.
  (model_create): Ask for a numeric revision and add code to initialize
   ra_session.
  (view_draw): Add back the logic that combines root and relpath for the
   header.
  (sub_main): Use numeric revisions and treat current path of browser as a
   relative path.

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

Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.c	Thu Apr  2 15:12:23 2026	(r1932741)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.c	Thu Apr  2 15:51:07 2026	(r1932742)
@@ -26,6 +26,7 @@
 
 #include "svn_client.h"
 #include "svn_opt.h"
+#include "svn_ra.h"
 #include "svn_path.h"
 #include "svn_pools.h"
 #include "svn_cmdline.h"
@@ -45,8 +46,8 @@ typedef struct svn_browse__item_t {
 /* a state of a single directory */
 typedef struct svn_browse__state_t {
   /* information about this node */
-  const char *abspath;
-  svn_opt_revision_t revision;
+  const char *relpath;
+  svn_revnum_t revision;
 
   /* stores the list of nodes in this state; an array of svn_browse__item_t */
   apr_array_header_t *list;
@@ -60,27 +61,24 @@ typedef struct svn_browse__state_t {
 
 typedef struct svn_browse__model_t {
   const char *root;
-  svn_opt_revision_t revision;
+  svn_revnum_t revision;
 
   svn_client_ctx_t *client;
+  svn_ra_session_t *session;
 
   svn_browse__state_t *current;
   apr_pool_t *pool;
 } svn_browse__model_t;
 
 static svn_error_t *
-list_cb(void *baton,
-        const char *path,
-        const svn_dirent_t *dirent,
-        const svn_lock_t *lock,
-        const char *abs_path,
-        const char *external_parent_url,
-        const char *external_target,
+list_cb(const char *relpath,
+        svn_dirent_t *dirent,
+        void *baton,
         apr_pool_t *scratch_pool)
 {
   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->relpath = svn_dirent_basename(relpath, state->pool);
   item->dirent = svn_dirent_dup(dirent, state->pool);
   APR_ARRAY_PUSH(state->list, svn_browse__item_t *) = item;
   return SVN_NO_ERROR;
@@ -88,36 +86,41 @@ list_cb(void *baton,
 
 static svn_error_t *
 state_create(svn_browse__state_t **state_p,
-             svn_client_ctx_t *ctx,
-             const char *url,
-             svn_opt_revision_t *revision,
+             svn_ra_session_t *session,
+             const char *relpath,
+             svn_revnum_t revision,
              apr_pool_t *result_pool,
              apr_pool_t *scratch_pool)
 {
   svn_browse__state_t *state = apr_pcalloc(result_pool, sizeof(*state));
+  svn_revnum_t revnum;
 
-  state->abspath = apr_pstrdup(result_pool, url);
+  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(url, revision, revision, NULL, svn_depth_immediates,
-                           SVN_DIRENT_ALL, TRUE, TRUE, list_cb, state, ctx,
-                           scratch_pool));
+  /* TODO: use svn_ra_get_dir2() as it automatically treats SVN_INVALID_REVNUM
+   * as HEAD and returns a list directly. */
+
+  SVN_ERR(svn_ra_get_latest_revnum(session, &revnum, scratch_pool));
+
+  SVN_ERR(svn_ra_list(session, relpath, revnum, NULL, svn_depth_immediates,
+                      SVN_DIRENT_ALL, list_cb, state, scratch_pool));
 
   *state_p = state;
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
-enter_path(svn_browse__model_t *ctx, const char *abspath,
+enter_path(svn_browse__model_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->client, abspath, &ctx->revision,
+  SVN_ERR(state_create(&newstate, ctx->session, relpath, ctx->revision,
                        state_pool, scratch_pool));
 
   /* switch to the next state and nuke the previous one */
@@ -130,13 +133,14 @@ enter_path(svn_browse__model_t *ctx, con
 static svn_error_t *
 model_create(svn_browse__model_t **model_p,
              const char *url,
-             svn_opt_revision_t revision,
+             svn_revnum_t revision,
              apr_pool_t *result_pool,
              apr_pool_t *scratch_pool)
 {
   svn_browse__model_t *model = apr_pcalloc(result_pool, sizeof(*model));
   svn_auth_baton_t *auth;
   svn_client_ctx_t *client;
+  svn_ra_session_t *session;
   apr_pool_t *state_pool;
   svn_browse__state_t *state;
 
@@ -148,15 +152,18 @@ model_create(svn_browse__model_t **model
   SVN_ERR(svn_client_create_context2(&client, NULL, result_pool));
   client->auth_baton = auth;
 
+  SVN_ERR(svn_client_open_ra_session2(&session, url, NULL, client, result_pool,
+                                      scratch_pool));
+
   /* the state should be in a separate pool so it's safe to free it */
   state_pool = svn_pool_create(result_pool);
-  SVN_ERR(state_create(&state, client, url, &revision, state_pool,
+  SVN_ERR(state_create(&state, session, "", revision, state_pool,
                        scratch_pool));
-
   /* TODO: we must use the repository root URL */
-  model->root = apr_pstrdup(result_pool, url);
+  SVN_ERR(svn_ra_get_session_url(session, &model->root, result_pool));
   model->revision = revision;
   model->client = client;
+  model->session = session;
   model->current = state;
   model->pool = result_pool;
 
@@ -181,8 +188,10 @@ static void
 view_draw(svn_browse__view_t *view, apr_pool_t *pool)
 {
   int i;
+  const char *abspath = svn_path_url_add_component2(
+      view->model->root, view->model->current->relpath, pool);
 
-  mvprintw(0, 4, "Browsing: %s", view->model->current->abspath);
+  mvprintw(0, 4, "Browsing: %s", abspath);
 
   for (i = 0; i < view->model->current->list->nelts; i++)
     {
@@ -215,7 +224,6 @@ static svn_error_t *
 sub_main(int *code, int argc, char *argv[], apr_pool_t *pool)
 {
   const char *url;
-  svn_opt_revision_t revision;
   svn_browse__model_t *ctx;
   svn_browse__view_t *view;
   apr_pool_t *iterpool;
@@ -225,9 +233,8 @@ sub_main(int *code, int argc, char *argv
                             "usage: svnbrowse <URL>");
 
   SVN_ERR(svn_uri_canonicalize_safe(&url, NULL, argv[1], pool, pool));
-  revision.kind = svn_opt_revision_head;
 
-  SVN_ERR(model_create(&ctx, url, revision, pool, pool));
+  SVN_ERR(model_create(&ctx, url, SVN_INVALID_REVNUM, pool, pool));
 
   /* init the display */
   initscr();
@@ -275,14 +282,14 @@ sub_main(int *code, int argc, char *argv
           case '\r':
             item = APR_ARRAY_IDX(ctx->current->list, ctx->current->selection,
                                  svn_browse__item_t *);
-            new_url = svn_path_url_add_component2(ctx->current->abspath,
-                                                  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_uri_dirname(ctx->current->abspath, 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.