Skip to content

Commit 4627794

Browse files
committed
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(). git-svn-id: https://svn.apache.org/repos/asf/subversion/trunk@1932903 13f79535-47bb-0310-9956-ffa450edef68
1 parent 69fceb7 commit 4627794

3 files changed

Lines changed: 73 additions & 39 deletions

File tree

subversion/svnbrowse/model.c

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
#include <apr.h>
2525

2626
#include "svn_client.h"
27-
#include "svn_cmdline.h"
2827
#include "svn_dirent_uri.h"
28+
#include "svn_path.h"
2929
#include "svn_ra.h"
3030
#include "svn_pools.h"
3131
#include "svn_error.h"
3232

33+
#include "private/svn_client_private.h"
34+
3335
#include "svnbrowse.h"
3436

3537
svn_error_t *
@@ -130,36 +132,65 @@ svn_browse__model_move_selection(svn_browse__model_t *model, int delta)
130132
svn_error_t *
131133
svn_browse__model_create(svn_browse__model_t **model_p,
132134
svn_client_ctx_t *ctx,
133-
const char *url,
134-
svn_revnum_t revision,
135+
const char *path_or_url,
136+
const svn_opt_revision_t *peg_revision,
137+
const svn_opt_revision_t *revision,
135138
apr_pool_t *result_pool,
136139
apr_pool_t *scratch_pool)
137140
{
138141
svn_browse__model_t *model = apr_pcalloc(result_pool, sizeof(*model));
139142
svn_ra_session_t *session;
140143
apr_pool_t *state_pool;
141-
svn_browse__state_t *state;
142144
const char *root, *relpath;
143145

144-
SVN_ERR(svn_client_open_ra_session2(&session, url, NULL, ctx, result_pool,
145-
scratch_pool));
146-
147-
SVN_ERR(svn_ra_get_repos_root2(session, &root, scratch_pool));
148-
SVN_ERR(svn_ra_reparent(session, root, scratch_pool));
146+
svn_opt_revision_t peg_rev = *peg_revision;
147+
svn_opt_revision_t start_rev = *revision;
148+
svn_client__pathrev_t *loc;
149149

150-
relpath = svn_uri_skip_ancestor(root, url, scratch_pool);
150+
/* Default revisions: peg -> working or head; operative -> peg. */
151+
SVN_ERR(svn_opt_resolve_revisions(&peg_rev, &start_rev,
152+
svn_path_is_url(path_or_url),
153+
TRUE /* notice_local_mods */,
154+
scratch_pool));
151155

152-
/* the state should be in a separate pool so it's safe to free it */
153-
state_pool = svn_pool_create(result_pool);
154-
SVN_ERR(svn_browse__state_create(&state, session, relpath, revision,
155-
state_pool, scratch_pool));
156+
SVN_ERR(svn_client__ra_session_from_path2(&session, &loc, path_or_url, NULL,
157+
&peg_rev, &start_rev, ctx,
158+
result_pool));
156159

157-
model->root = apr_pstrdup(result_pool, root);
158-
model->revision = revision;
160+
model->root = apr_pstrdup(result_pool, loc->repos_root_url);
159161
model->client = ctx;
160162
model->session = session;
161-
model->current = state;
162-
model->pool = result_pool;
163+
164+
/* If the revision is ovbiously HEAD, we are not going to use the resolved
165+
* revnum, but rely on svn_ra_get_dir2() doing that for us. It allows the
166+
* browser to always browse on the latest revision and catch-up recent
167+
* commits as session is active.
168+
*
169+
* Note: only head+head combination of peg_revision and revision should be
170+
* considered as the "real" head. If we were to for example go to r123 and
171+
* then resolve HEAD, its value may change as session progresses. This logic
172+
* would be too complicated and rather confusing. That's why we will fallback
173+
* to what the client is doing instead of reinventing the wheel.
174+
*
175+
* When invoked from a working copy, it's not HEAD either. It's should point
176+
* to WORKING, i.e. revnum should not change. Again rescanning the working
177+
* copy is possible but we assume it never changes.
178+
*/
179+
180+
if (peg_rev.kind == svn_opt_revision_head &&
181+
start_rev.kind == svn_opt_revision_head)
182+
model->revision = SVN_INVALID_REVNUM;
183+
else
184+
model->revision = loc->rev;
185+
186+
SVN_ERR(svn_ra_reparent(session, loc->repos_root_url, scratch_pool));
187+
188+
relpath = svn_uri_skip_ancestor(loc->repos_root_url, loc->url, scratch_pool);
189+
190+
/* the state should be in a separate pool so it's safe to free it */
191+
state_pool = svn_pool_create(result_pool);
192+
SVN_ERR(svn_browse__state_create(&model->current, session, relpath,
193+
model->revision, state_pool, scratch_pool));
163194

164195
*model_p = model;
165196
return SVN_NO_ERROR;

subversion/svnbrowse/svnbrowse.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ show_version(apr_pool_t *scratch_pool,
217217
static svn_error_t *
218218
sub_main(int *code, int argc, const char *argv[], apr_pool_t *pool)
219219
{
220-
const char *url;
221220
svn_client_ctx_t *client;
222221
svn_auth_baton_t *auth;
223222
svn_browse__model_t *ctx;
@@ -226,6 +225,7 @@ sub_main(int *code, int argc, const char *argv[], apr_pool_t *pool)
226225
svn_boolean_t read_pass_from_stdin = FALSE;
227226
apr_pool_t *iterpool;
228227
apr_getopt_t *os;
228+
apr_array_header_t *targets = NULL;
229229

230230
opt_state.revision.kind = svn_opt_revision_head;
231231
opt_state.config_options =
@@ -313,20 +313,6 @@ sub_main(int *code, int argc, const char *argv[], apr_pool_t *pool)
313313
return SVN_NO_ERROR;
314314
}
315315

316-
/* TODO: WC paths are not implemented; svn_uri_canonicalize_safe() will just
317-
* fail in case of one */
318-
url = (os->ind < argc) ? os->argv[os->ind++] : ".";
319-
SVN_ERR(svn_uri_canonicalize_safe(&url, NULL, url, pool, pool));
320-
321-
/* we must fail if there are extra arguments */
322-
if (os->ind < argc - 1)
323-
{
324-
printf("%d\n", os->ind);
325-
*code = EXIT_FAILURE;
326-
SVN_ERR(show_usage(pool));
327-
return SVN_NO_ERROR;
328-
}
329-
330316
SVN_ERR(svn_config_ensure(opt_state.config_dir, pool));
331317

332318
/* Set up Authentication stuff. */
@@ -348,8 +334,23 @@ sub_main(int *code, int argc, const char *argv[], apr_pool_t *pool)
348334
SVN_ERR(svn_client_create_context2(&client, NULL, pool));
349335
client->auth_baton = auth;
350336

351-
SVN_ERR(svn_browse__model_create(&ctx, client, url, SVN_INVALID_REVNUM, pool,
352-
pool));
337+
SVN_ERR(svn_client_args_to_target_array2(&targets, os, NULL, client, FALSE,
338+
pool));
339+
340+
/* we must fail if there are extra arguments */
341+
if (targets->nelts != 1)
342+
{
343+
*code = EXIT_FAILURE;
344+
SVN_ERR(show_usage(pool));
345+
return SVN_NO_ERROR;
346+
}
347+
348+
SVN_ERR(svn_opt_parse_path(&opt_state.peg_revision, &opt_state.path_or_url,
349+
APR_ARRAY_IDX(targets, 0, const char *), pool));
350+
351+
SVN_ERR(svn_browse__model_create(&ctx, client, opt_state.path_or_url,
352+
&opt_state.peg_revision,
353+
&opt_state.revision, pool, pool));
353354

354355
/* init the display */
355356
initscr();

subversion/svnbrowse/svnbrowse.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,12 @@ typedef struct svn_browse__opt_state_t {
4848

4949
const char *auth_username; /* auth username */
5050
const char *auth_password; /* auth password */
51-
apr_array_header_t *targets; /* target list from file */
5251
svn_boolean_t no_auth_cache; /* do not cache authentication information */
5352
const char *config_dir; /* over-riding configuration directory */
5453
apr_array_header_t *config_options; /* over-riding configuration options */
55-
svn_opt_revision_t revision;
54+
svn_opt_revision_t revision; /* --revision */
55+
const char *path_or_url;
56+
svn_opt_revision_t peg_revision; /* @PEGREV*/
5657

5758
/* trust server SSL certs that would otherwise be rejected as "untrusted" */
5859
svn_boolean_t trust_server_cert_unknown_ca;
@@ -125,7 +126,8 @@ svn_browse__model_move_selection(svn_browse__model_t *model,
125126
svn_error_t *
126127
svn_browse__model_create(svn_browse__model_t **model_p,
127128
svn_client_ctx_t *ctx,
128-
const char *url,
129-
svn_revnum_t revision,
129+
const char *path_or_url,
130+
const svn_opt_revision_t *peg_revision,
131+
const svn_opt_revision_t *revision,
130132
apr_pool_t *result_pool,
131133
apr_pool_t *scratch_pool);

0 commit comments

Comments
 (0)