Author: rinrab
Date: Wed Apr 8 14:08:39 2026
New Revision: 1932903
Log:
svnbrowse: Support proper revision/target system in the command-line handling.
The model, when created, will accept a path_or_url parameter and, if a path is
supplied, go and get the URL from WC. It also receives a revision/peg_revision
as svn_opt_revision_t. The standard client framework will be used to resolve
those. If both of those revisions are HEAD, we'll directly read directories at
HEAD.
* subversion/svnbrowse/svnbrowse.h
(svn_browse__opt_state_t): Add revision, peg_revision, and path_or_url to
the struct.
(svn_browse__model_create): Update function declaration.
* subversion/svnbrowse/model.c
(includes): Update includes.
(svn_browse__model_create): Update arguments that the function accepts, use
svn_client__ra_session_from_path2() instead of svn_client_open_ra_session2()
for initializing RA sessions, and use the revision/URL it resolves for the
newly created model.
* subversion/svnbrowse/svnbrowse.c
(sub_main): Handle all extra args with svn_client_args_to_target_array2() and
extract "the target" from it (the array should only contain of those). Parse
this target onto peg_revision and path_or_url using svn_opt_parse_path().
Modified:
subversion/trunk/subversion/svnbrowse/model.c
subversion/trunk/subversion/svnbrowse/svnbrowse.c
subversion/trunk/subversion/svnbrowse/svnbrowse.h
Modified: subversion/trunk/subversion/svnbrowse/model.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/model.c Wed Apr 8 14:08:31 2026 (r1932902)
+++ subversion/trunk/subversion/svnbrowse/model.c Wed Apr 8 14:08:39 2026 (r1932903)
@@ -24,12 +24,14 @@
#include <apr.h>
#include "svn_client.h"
-#include "svn_cmdline.h"
#include "svn_dirent_uri.h"
+#include "svn_path.h"
#include "svn_ra.h"
#include "svn_pools.h"
#include "svn_error.h"
+#include "private/svn_client_private.h"
+
#include "svnbrowse.h"
svn_error_t *
@@ -130,36 +132,65 @@ svn_browse__model_move_selection(svn_bro
svn_error_t *
svn_browse__model_create(svn_browse__model_t **model_p,
svn_client_ctx_t *ctx,
- const char *url,
- svn_revnum_t revision,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
svn_browse__model_t *model = apr_pcalloc(result_pool, sizeof(*model));
svn_ra_session_t *session;
apr_pool_t *state_pool;
- svn_browse__state_t *state;
const char *root, *relpath;
- SVN_ERR(svn_client_open_ra_session2(&session, url, NULL, ctx, result_pool,
- scratch_pool));
+ svn_opt_revision_t peg_rev = *peg_revision;
+ svn_opt_revision_t start_rev = *revision;
+ svn_client__pathrev_t *loc;
+
+ /* Default revisions: peg -> working or head; operative -> peg. */
+ SVN_ERR(svn_opt_resolve_revisions(&peg_rev, &start_rev,
+ svn_path_is_url(path_or_url),
+ TRUE /* notice_local_mods */,
+ scratch_pool));
+
+ SVN_ERR(svn_client__ra_session_from_path2(&session, &loc, path_or_url, NULL,
+ &peg_rev, &start_rev, ctx,
+ result_pool));
+
+ model->root = apr_pstrdup(result_pool, loc->repos_root_url);
+ model->client = ctx;
+ model->session = session;
- SVN_ERR(svn_ra_get_repos_root2(session, &root, scratch_pool));
- SVN_ERR(svn_ra_reparent(session, root, scratch_pool));
+ /* If the revision is ovbiously HEAD, we are not going to use the resolved
+ * revnum, but rely on svn_ra_get_dir2() doing that for us. It allows the
+ * browser to always browse on the latest revision and catch-up recent
+ * commits as session is active.
+ *
+ * Note: only head+head combination of peg_revision and revision should be
+ * considered as the "real" head. If we were to for example go to r123 and
+ * then resolve HEAD, its value may change as session progresses. This logic
+ * would be too complicated and rather confusing. That's why we will fallback
+ * to what the client is doing instead of reinventing the wheel.
+ *
+ * When invoked from a working copy, it's not HEAD either. It's should point
+ * to WORKING, i.e. revnum should not change. Again rescanning the working
+ * copy is possible but we assume it never changes.
+ */
+
+ if (peg_rev.kind == svn_opt_revision_head &&
+ start_rev.kind == svn_opt_revision_head)
+ model->revision = SVN_INVALID_REVNUM;
+ else
+ model->revision = loc->rev;
- relpath = svn_uri_skip_ancestor(root, url, scratch_pool);
+ SVN_ERR(svn_ra_reparent(session, loc->repos_root_url, scratch_pool));
+
+ relpath = svn_uri_skip_ancestor(loc->repos_root_url, loc->url, 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(svn_browse__state_create(&state, session, relpath, revision,
- state_pool, scratch_pool));
-
- model->root = apr_pstrdup(result_pool, root);
- model->revision = revision;
- model->client = ctx;
- model->session = session;
- model->current = state;
- model->pool = result_pool;
+ SVN_ERR(svn_browse__state_create(&model->current, session, relpath,
+ model->revision, state_pool, scratch_pool));
*model_p = model;
return SVN_NO_ERROR;
Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.c
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.c Wed Apr 8 14:08:31 2026 (r1932902)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.c Wed Apr 8 14:08:39 2026 (r1932903)
@@ -217,7 +217,6 @@ show_version(apr_pool_t *scratch_pool,
static svn_error_t *
sub_main(int *code, int argc, const char *argv[], apr_pool_t *pool)
{
- const char *url;
svn_client_ctx_t *client;
svn_auth_baton_t *auth;
svn_browse__model_t *ctx;
@@ -226,6 +225,7 @@ sub_main(int *code, int argc, const char
svn_boolean_t read_pass_from_stdin = FALSE;
apr_pool_t *iterpool;
apr_getopt_t *os;
+ apr_array_header_t *targets = NULL;
opt_state.revision.kind = svn_opt_revision_head;
opt_state.config_options =
@@ -313,20 +313,6 @@ sub_main(int *code, int argc, const char
return SVN_NO_ERROR;
}
- /* TODO: WC paths are not implemented; svn_uri_canonicalize_safe() will just
- * fail in case of one */
- url = (os->ind < argc) ? os->argv[os->ind++] : ".";
- SVN_ERR(svn_uri_canonicalize_safe(&url, NULL, url, pool, pool));
-
- /* we must fail if there are extra arguments */
- if (os->ind < argc - 1)
- {
- printf("%d\n", os->ind);
- *code = EXIT_FAILURE;
- SVN_ERR(show_usage(pool));
- return SVN_NO_ERROR;
- }
-
SVN_ERR(svn_config_ensure(opt_state.config_dir, pool));
/* Set up Authentication stuff. */
@@ -348,8 +334,23 @@ sub_main(int *code, int argc, const char
SVN_ERR(svn_client_create_context2(&client, NULL, pool));
client->auth_baton = auth;
- SVN_ERR(svn_browse__model_create(&ctx, client, url, SVN_INVALID_REVNUM, pool,
- pool));
+ SVN_ERR(svn_client_args_to_target_array2(&targets, os, NULL, client, FALSE,
+ pool));
+
+ /* we must fail if there are extra arguments */
+ if (targets->nelts != 1)
+ {
+ *code = EXIT_FAILURE;
+ SVN_ERR(show_usage(pool));
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_opt_parse_path(&opt_state.peg_revision, &opt_state.path_or_url,
+ APR_ARRAY_IDX(targets, 0, const char *), pool));
+
+ SVN_ERR(svn_browse__model_create(&ctx, client, opt_state.path_or_url,
+ &opt_state.peg_revision,
+ &opt_state.revision, pool, pool));
/* init the display */
initscr();
Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.h
==============================================================================
--- subversion/trunk/subversion/svnbrowse/svnbrowse.h Wed Apr 8 14:08:31 2026 (r1932902)
+++ subversion/trunk/subversion/svnbrowse/svnbrowse.h Wed Apr 8 14:08:39 2026 (r1932903)
@@ -48,11 +48,12 @@ typedef struct svn_browse__opt_state_t {
const char *auth_username; /* auth username */
const char *auth_password; /* auth password */
- apr_array_header_t *targets; /* target list from file */
svn_boolean_t no_auth_cache; /* do not cache authentication information */
const char *config_dir; /* over-riding configuration directory */
apr_array_header_t *config_options; /* over-riding configuration options */
- svn_opt_revision_t revision;
+ svn_opt_revision_t revision; /* --revision */
+ const char *path_or_url;
+ svn_opt_revision_t peg_revision; /* @PEGREV*/
/* trust server SSL certs that would otherwise be rejected as "untrusted" */
svn_boolean_t trust_server_cert_unknown_ca;
@@ -125,7 +126,8 @@ svn_browse__model_move_selection(svn_bro
svn_error_t *
svn_browse__model_create(svn_browse__model_t **model_p,
svn_client_ctx_t *ctx,
- const char *url,
- svn_revnum_t revision,
+ const char *path_or_url,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
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.