Author: rinrab
Date: Fri Sep 4 10:56:01 2026
New Revision: 1937857
Log:
On the 'reparentless' branch: Implement reparentless get_dir, check_path,
and stat methods.
* subversion/include/svn_ra.h
(svn_ra_get_dir3, svn_ra_check_path2, svn_ra_stat2): Bump version, update
description.
(svn_ra_get_dir2, svn_ra_check_path, svn_ra_stat): Deprecate.
* subversion/libsvn_ra/deprecated.c
(get_session_path): New function.
(svn_ra_get_dir): Wrap svn_ra_get_dir2() instead of direct vtable call.
(svn_ra_get_dir2, svn_ra_check_path, svn_ra_stat): Implement.
* subversion/libsvn_ra/ra_loader.c
(svn_ra_get_dir3, svn_ra_check_path2, svn_ra_stat2): Bump functions, rename
path to repos_relpath.
(svn_ra_stat2): Temporary disable backward compat fallback code.
(svn_ra__vtable_t::get_dir, svn_ra__vtable_t::check_path,
svn_ra__vtable_t::stat): Rename path -> repos_relpath, update links
to svn_ra* functions.
* subversion/libsvn_ra_local/ra_plugin.c
(svn_ra_local__do_check_path, svn_ra_local__stat, svn_ra_local__get_dir):
Update declaration, pass repos_relpath further into svn_repos/svn_fs API.
* subversion/libsvn_ra_serf/ra_serf.h
(svn_ra_serf__resolve_path, svn_ra_serf__get_stable_url2): Declare functions.
* subversion/libsvn_ra_serf/util.c
(svn_ra_serf__resolve_path): Implement function.
* subversion/libsvn_ra_serf/property.c
(svn_ra_serf__get_stable_url2): Implement function.
* subversion/libsvn_ra_serf/stat.c
(svn_ra_serf__check_path, svn_ra_serf__stat, svn_ra_serf__get_dir): Update
declaration, remove session URL handling, use repos_root instead.
* subversion/libsvn_ra_svn/client.c
(reparent_repos_relpath): New function that resolves the path, potentially
reparenting the session.
(ra_svn_get_dir, ra_svn_check_path, ra_svn_stat): Update functions to use the
new design.
Modified:
subversion/branches/reparentless/subversion/include/svn_ra.h
subversion/branches/reparentless/subversion/libsvn_ra/deprecated.c
subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.c
subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.h
subversion/branches/reparentless/subversion/libsvn_ra_local/ra_plugin.c
subversion/branches/reparentless/subversion/libsvn_ra_serf/property.c
subversion/branches/reparentless/subversion/libsvn_ra_serf/ra_serf.h
subversion/branches/reparentless/subversion/libsvn_ra_serf/stat.c
subversion/branches/reparentless/subversion/libsvn_ra_serf/util.c
subversion/branches/reparentless/subversion/libsvn_ra_svn/client.c
Modified: subversion/branches/reparentless/subversion/include/svn_ra.h
==============================================================================
--- subversion/branches/reparentless/subversion/include/svn_ra.h Fri Sep
4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/include/svn_ra.h Fri Sep
4 10:56:01 2026 (r1937857)
@@ -1103,8 +1103,8 @@ svn_ra_get_file(svn_ra_session_t *sessio
/**
* If @a dirents is non @c NULL, set @a *dirents to contain all the entries
- * of directory @a path at @a revision. The keys of @a dirents will be
- * entry names (<tt>const char *</tt>), and the values dirents
+ * of directory @a repos_relpath at @a revision. The keys of @a dirents will
+ * be entry names (<tt>const char *</tt>), and the values dirents
* (<tt>@c svn_dirent_t *</tt>). Use @a pool for all allocations.
*
* @a dirent_fields controls which portions of the <tt>@c svn_dirent_t</tt>
@@ -1112,7 +1112,7 @@ svn_ra_get_file(svn_ra_session_t *sessio
* @c SVN_DIRENT_ALL, otherwise pass the bitwise OR of all the @c SVN_DIRENT_
* fields you would like to have returned to you.
*
- * @a path is interpreted relative to the URL in @a session.
+ * @a repos_relpath is interpreted as a path relative to the repository root.
*
* If @a revision is @c SVN_INVALID_REVNUM (meaning 'head') and
* @a fetched_rev is not @c NULL, then this function will set
@@ -1125,8 +1125,26 @@ svn_ra_get_file(svn_ra_session_t *sessio
* #svn_prop_entry_kind properties). The keys are <tt>const char *</tt>,
* values are <tt>@c svn_string_t *</tt>.
*
+ * @since New in 1.16.
+ */
+svn_error_t *
+svn_ra_get_dir3(svn_ra_session_t *session,
+ apr_hash_t **dirents,
+ svn_revnum_t *fetched_rev,
+ apr_hash_t **props,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ apr_uint32_t dirent_fields,
+ apr_pool_t *pool);
+
+/**
+ * Similar to @c svn_ra_get_dir3, but @a path is relative to session URL.
+ *
* @since New in 1.4.
+ *
+ * @deprecated Provided for compatibility with the 1.15 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_ra_get_dir2(svn_ra_session_t *session,
apr_hash_t **dirents,
@@ -1716,14 +1734,31 @@ svn_ra_get_log(svn_ra_session_t *session
apr_pool_t *pool);
/**
- * Set @a *kind to the node kind associated with @a path at @a revision.
- * If @a path does not exist under @a revision, set @a *kind to
- * @c svn_node_none. @a path is relative to the @a session's parent URL.
+ * Set @a *kind to the node kind associated with @a repos_relpath at @a
+ * revision. If @a repos_relpath does not exist under @a revision, set @a
*kind
+ * to @c svn_node_none. @a repos_relpath is a path relative to repository
+ * root.
*
* Use @a pool for memory allocation.
*
+ * @since New in 1.16.
+ */
+svn_error_t *
+svn_ra_check_path2(svn_ra_session_t *session,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ svn_node_kind_t *kind,
+ apr_pool_t *pool);
+
+
+/**
+ * Similar to @c svn_ra_check_path2, but @a path is relative to session URL.
+ *
* @since New in 1.2.
+ *
+ * @deprecated Provided for compatibility with the 1.15 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_ra_check_path(svn_ra_session_t *session,
const char *path,
@@ -1732,14 +1767,30 @@ svn_ra_check_path(svn_ra_session_t *sess
apr_pool_t *pool);
/**
- * Set @a *dirent to an @c svn_dirent_t associated with @a path at @a
- * revision. @a path is relative to the @a session's parent's URL.
- * If @a path does not exist in @a revision, set @a *dirent to NULL.
+ * Set @a *dirent to an @c svn_dirent_t associated with @a repos_relpath at @a
+ * revision. @a repos_relpath is a path relative to the repository root.
+ *
+ * If @a repos_relpath does not exist in @a revision, set @a *dirent to NULL.
*
* Use @a pool for memory allocation.
*
+ * @since New in 1.16.
+ */
+svn_error_t *
+svn_ra_stat2(svn_ra_session_t *session,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ svn_dirent_t **dirent,
+ apr_pool_t *pool);
+
+/**
+ * Similar to @c svn_ra_stat2, but @a path is relative to session URL.
+ *
* @since New in 1.2.
+ *
+ * @deprecated Provided for compatibility with the 1.15 API.
*/
+SVN_DEPRECATED
svn_error_t *
svn_ra_stat(svn_ra_session_t *session,
const char *path,
Modified: subversion/branches/reparentless/subversion/libsvn_ra/deprecated.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra/deprecated.c Fri Sep
4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra/deprecated.c Fri Sep
4 10:56:01 2026 (r1937857)
@@ -215,6 +215,21 @@ svn_error_t *svn_ra_open(svn_ra_session_
config, pool);
}
+/* Read session path - session URL relative to the repository root. */
+static svn_error_t *
+get_session_path(svn_ra_session_t *session,
+ const char **path_p,
+ apr_pool_t *pool)
+{
+ const char *session_url, *repos_root;
+
+ SVN_ERR(svn_ra_get_session_url(session, &session_url, pool));
+ SVN_ERR(svn_ra_get_repos_root2(session, &repos_root, pool));
+
+ *path_p = svn_uri_skip_ancestor(repos_root, session_url, pool);
+ return SVN_NO_ERROR;
+}
+
svn_error_t *svn_ra_change_rev_prop(svn_ra_session_t *session,
svn_revnum_t rev,
const char *name,
@@ -497,10 +512,67 @@ svn_error_t *svn_ra_get_dir(svn_ra_sessi
apr_pool_t *pool)
{
SVN_ERR_ASSERT(*path != '/');
- return session->vtable->get_dir(session, dirents, fetched_rev, props,
- path, revision, SVN_DIRENT_ALL, pool);
+ return svn_ra_get_dir2(session, dirents, fetched_rev, props,
+ path, revision, SVN_DIRENT_ALL, pool);
+}
+
+svn_error_t *svn_ra_get_dir2(svn_ra_session_t *session,
+ apr_hash_t **dirents,
+ svn_revnum_t *fetched_rev,
+ apr_hash_t **props,
+ const char *path,
+ svn_revnum_t revision,
+ apr_uint32_t dirent_fields,
+ apr_pool_t *pool)
+{
+ const char *session_path;
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
+
+ SVN_ERR(get_session_path(session, &session_path, pool));
+ SVN_ERR(svn_ra_get_dir3(session, dirents, fetched_rev, props,
+ svn_relpath_join(session_path, path, pool),
+ revision, dirent_fields, pool));
+
+ return SVN_NO_ERROR;
}
+svn_error_t *
+svn_ra_stat(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ svn_dirent_t **dirent,
+ apr_pool_t *pool)
+{
+ const char *session_path;
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
+
+ SVN_ERR(get_session_path(session, &session_path, pool));
+ SVN_ERR(svn_ra_stat2(session,
+ svn_relpath_join(session_path, path, pool),
+ revision, dirent, pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_ra_check_path(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ svn_node_kind_t *kind,
+ apr_pool_t *pool)
+{
+ const char *session_path;
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
+
+ SVN_ERR(get_session_path(session, &session_path, pool));
+ SVN_ERR(svn_ra_check_path2(session,
+ svn_relpath_join(session_path, path, pool),
+ revision, kind, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
/* For each libsvn_ra_foo library, provide an implementation of deprecated
svn_ra_foo_init function that wraps svn_ra_foo__compat_init, or returns
a "not implemented" error if it was not linked. */
Modified: subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.c Fri Sep
4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.c Fri Sep
4 10:56:01 2026 (r1937857)
@@ -637,18 +637,20 @@ svn_error_t *svn_ra_get_file(svn_ra_sess
fetched_rev, props, pool);
}
-svn_error_t *svn_ra_get_dir2(svn_ra_session_t *session,
- apr_hash_t **dirents,
- svn_revnum_t *fetched_rev,
- apr_hash_t **props,
- const char *path,
- svn_revnum_t revision,
- apr_uint32_t dirent_fields,
- apr_pool_t *pool)
+svn_error_t *
+svn_ra_get_dir3(svn_ra_session_t *session,
+ apr_hash_t **dirents,
+ svn_revnum_t *fetched_rev,
+ apr_hash_t **props,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ apr_uint32_t dirent_fields,
+ apr_pool_t *pool)
{
- SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(repos_relpath));
return session->vtable->get_dir(session, dirents, fetched_rev, props,
- path, revision, dirent_fields, pool);
+ repos_relpath, revision, dirent_fields,
+ pool);
}
svn_error_t *
@@ -831,26 +833,28 @@ svn_error_t *svn_ra_get_log2(svn_ra_sess
receiver, receiver_baton, pool);
}
-svn_error_t *svn_ra_check_path(svn_ra_session_t *session,
- const char *path,
- svn_revnum_t revision,
- svn_node_kind_t *kind,
- apr_pool_t *pool)
+svn_error_t *svn_ra_check_path2(svn_ra_session_t *session,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ svn_node_kind_t *kind,
+ apr_pool_t *pool)
{
- SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
- return session->vtable->check_path(session, path, revision, kind, pool);
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(repos_relpath));
+ return session->vtable->check_path(session, repos_relpath, revision, kind,
+ pool);
}
-svn_error_t *svn_ra_stat(svn_ra_session_t *session,
- const char *path,
- svn_revnum_t revision,
- svn_dirent_t **dirent,
- apr_pool_t *pool)
+svn_error_t *svn_ra_stat2(svn_ra_session_t *session,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ svn_dirent_t **dirent,
+ apr_pool_t *pool)
{
svn_error_t *err;
- SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
- err = session->vtable->stat(session, path, revision, dirent, pool);
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(repos_relpath));
+ err = session->vtable->stat(session, repos_relpath, revision, dirent, pool);
+#if 0
/* svnserve before 1.2 doesn't support the above, so fall back on
a far less efficient, but still correct method. */
if (err && err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)
@@ -862,7 +866,7 @@ svn_error_t *svn_ra_stat(svn_ra_session_
svn_error_clear(err);
- SVN_ERR(svn_ra_check_path(session, path, revision, &kind, scratch_pool));
+- SVN_ERR(svn_ra_check_path(session, path, revision, &kind,
scratch_pool));
if (kind != svn_node_none)
{
@@ -943,6 +947,7 @@ svn_error_t *svn_ra_stat(svn_ra_session_
}
else
SVN_ERR(err);
+#endif
return SVN_NO_ERROR;
}
Modified: subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.h
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.h Fri Sep
4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.h Fri Sep
4 10:56:01 2026 (r1937857)
@@ -139,12 +139,12 @@ typedef struct svn_ra__vtable_t {
svn_revnum_t *fetched_rev,
apr_hash_t **props,
apr_pool_t *pool);
- /* See svn_ra_get_dir2(). */
+ /* See svn_ra_get_dir3(). */
svn_error_t *(*get_dir)(svn_ra_session_t *session,
apr_hash_t **dirents,
svn_revnum_t *fetched_rev,
apr_hash_t **props,
- const char *path,
+ const char *repos_relpath,
svn_revnum_t revision,
apr_uint32_t dirent_fields,
apr_pool_t *pool);
@@ -219,15 +219,15 @@ typedef struct svn_ra__vtable_t {
svn_log_entry_receiver_t receiver,
void *receiver_baton,
apr_pool_t *pool);
- /* See svn_ra_check_path(). */
+ /* See svn_ra_check_path2(). */
svn_error_t *(*check_path)(svn_ra_session_t *session,
- const char *path,
+ const char *repos_relpath,
svn_revnum_t revision,
svn_node_kind_t *kind,
apr_pool_t *pool);
- /* See svn_ra_stat(). */
+ /* See svn_ra_stat2(). */
svn_error_t *(*stat)(svn_ra_session_t *session,
- const char *path,
+ const char *repos_relpath,
svn_revnum_t revision,
svn_dirent_t **dirent,
apr_pool_t *pool);
Modified:
subversion/branches/reparentless/subversion/libsvn_ra_local/ra_plugin.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_local/ra_plugin.c
Fri Sep 4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra_local/ra_plugin.c
Fri Sep 4 10:56:01 2026 (r1937857)
@@ -1180,38 +1180,36 @@ svn_ra_local__get_log(svn_ra_session_t *
static svn_error_t *
svn_ra_local__do_check_path(svn_ra_session_t *session,
- const char *path,
+ const char *repos_relpath,
svn_revnum_t revision,
svn_node_kind_t *kind,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sess = session->priv;
svn_fs_root_t *root;
- const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
if (! SVN_IS_VALID_REVNUM(revision))
SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));
SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, pool));
- return svn_fs_check_path(kind, root, abs_path, pool);
+ return svn_fs_check_path(kind, root, repos_relpath, pool);
}
static svn_error_t *
svn_ra_local__stat(svn_ra_session_t *session,
- const char *path,
+ const char *repos_relpath,
svn_revnum_t revision,
svn_dirent_t **dirent,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sess = session->priv;
svn_fs_root_t *root;
- const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
if (! SVN_IS_VALID_REVNUM(revision))
SVN_ERR(svn_fs_youngest_rev(&revision, sess->fs, pool));
SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, pool));
- return svn_repos_stat(dirent, root, abs_path, pool);
+ return svn_repos_stat(dirent, root, repos_relpath, pool);
}
@@ -1330,7 +1328,7 @@ svn_ra_local__get_dir(svn_ra_session_t *
apr_hash_t **dirents,
svn_revnum_t *fetched_rev,
apr_hash_t **props,
- const char *path,
+ const char *repos_relpath,
svn_revnum_t revision,
apr_uint32_t dirent_fields,
apr_pool_t *pool)
@@ -1340,7 +1338,6 @@ svn_ra_local__get_dir(svn_ra_session_t *
apr_hash_t *entries;
apr_hash_index_t *hi;
svn_ra_local__session_baton_t *sess = session->priv;
- const char *abs_path = svn_fspath__join(sess->fs_path->data, path, pool);
/* Open the revision's root. */
if (! SVN_IS_VALID_REVNUM(revision))
@@ -1357,7 +1354,7 @@ svn_ra_local__get_dir(svn_ra_session_t *
{
apr_pool_t *iterpool = svn_pool_create(pool);
/* Get the dir's entries. */
- SVN_ERR(svn_fs_dir_entries(&entries, root, abs_path, pool));
+ SVN_ERR(svn_fs_dir_entries(&entries, root, repos_relpath, pool));
/* Loop over the fs dirents, and build a hash of general
svn_dirent_t's. */
@@ -1376,7 +1373,7 @@ svn_ra_local__get_dir(svn_ra_session_t *
entryname = (const char *) key;
fs_entry = (svn_fs_dirent_t *) val;
- fullpath = svn_dirent_join(abs_path, entryname, iterpool);
+ fullpath = svn_dirent_join(repos_relpath, entryname, iterpool);
if (dirent_fields & SVN_DIRENT_KIND)
{
@@ -1426,7 +1423,7 @@ svn_ra_local__get_dir(svn_ra_session_t *
/* Handle props if requested. */
if (props)
- SVN_ERR(get_node_props(props, root, abs_path, sess->uuid, pool, pool));
+ SVN_ERR(get_node_props(props, root, repos_relpath, sess->uuid, pool,
pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/reparentless/subversion/libsvn_ra_serf/property.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_serf/property.c
Fri Sep 4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra_serf/property.c
Fri Sep 4 10:56:01 2026 (r1937857)
@@ -876,6 +876,31 @@ svn_ra_serf__get_stable_url(const char *
svn_error_t *
+svn_ra_serf__get_stable_url2(const char **stable_url,
+ svn_revnum_t *latest_revnum,
+ svn_ra_serf__session_t *session,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *basecoll_url;
+ svn_revnum_t revnum_used;
+
+ SVN_ERR(get_baseline_info(&basecoll_url, &revnum_used,
+ session, revision, scratch_pool, scratch_pool));
+
+ *stable_url = svn_path_url_add_component2(basecoll_url, repos_relpath,
+ result_pool);
+ if (latest_revnum)
+ *latest_revnum = revnum_used;
+
+ return SVN_NO_ERROR;
+}
+
+
+
+svn_error_t *
svn_ra_serf__fetch_dav_prop(const char **value,
svn_ra_serf__session_t *session,
const char *url,
Modified: subversion/branches/reparentless/subversion/libsvn_ra_serf/ra_serf.h
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_serf/ra_serf.h
Fri Sep 4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra_serf/ra_serf.h
Fri Sep 4 10:56:01 2026 (r1937857)
@@ -1180,6 +1180,18 @@ svn_ra_serf__get_stable_url(const char *
apr_pool_t *scratch_pool);
+/** Similar to svn_ra_serf__get_stable_url, but using a resolved REPOS_RELPATH
+ * instead of URL */
+svn_error_t *
+svn_ra_serf__get_stable_url2(const char **stable_url,
+ svn_revnum_t *latest_revnum,
+ svn_ra_serf__session_t *session,
+ const char *repos_relpath,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
/** RA functions **/
/* Implements svn_ra__vtable_t.reparent(). */
@@ -1597,6 +1609,12 @@ svn_ra_serf__uri_parse(apr_uri_t *uri,
const char *url_str,
apr_pool_t *result_pool);
+svn_error_t *
+svn_ra_serf__resolve_path(svn_ra_session_t *ra_session,
+ const char **path,
+ const char *repos_relpath,
+ apr_pool_t *result_pool);
+
/* Setup the "Accept-Encoding" header value for requests that expect
svndiff-encoded deltas, depending on the SESSION state. */
void
Modified: subversion/branches/reparentless/subversion/libsvn_ra_serf/stat.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_serf/stat.c Fri Sep
4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra_serf/stat.c Fri Sep
4 10:56:01 2026 (r1937857)
@@ -51,7 +51,7 @@
/* Implements svn_ra__vtable_t.check_path(). */
svn_error_t *
svn_ra_serf__check_path(svn_ra_session_t *ra_session,
- const char *relpath,
+ const char *repos_relpath,
svn_revnum_t revision,
svn_node_kind_t *kind,
apr_pool_t *scratch_pool)
@@ -59,28 +59,27 @@ svn_ra_serf__check_path(svn_ra_session_t
svn_ra_serf__session_t *session = ra_session->priv;
apr_hash_t *props;
svn_error_t *err;
- const char *url;
-
- url = session->session_url.path;
-
- /* If we have a relative path, append it. */
- if (relpath)
- url = svn_path_url_add_component2(url, relpath, scratch_pool);
+ const char *path;
/* If we were given a specific revision, get a URL that refers to that
specific revision (rather than floating with HEAD). */
if (SVN_IS_VALID_REVNUM(revision))
{
- SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */,
- session,
- url, revision,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_ra_serf__get_stable_url2(&path, NULL /* latest_revnum */,
+ session,
+ repos_relpath, revision,
+ scratch_pool, scratch_pool));
+ }
+ else
+ {
+ SVN_ERR(svn_ra_serf__resolve_path(ra_session, &path, repos_relpath,
+ scratch_pool));
}
/* URL is stable, so we use SVN_INVALID_REVNUM since it is now irrelevant.
Or we started with SVN_INVALID_REVNUM and URL may be floating. */
err = svn_ra_serf__fetch_node_props(&props, session,
- url, SVN_INVALID_REVNUM,
+ path, SVN_INVALID_REVNUM,
check_path_props,
scratch_pool, scratch_pool);
@@ -229,7 +228,7 @@ get_dirent_props(apr_uint32_t dirent_fie
/* Implements svn_ra__vtable_t.stat(). */
svn_error_t *
svn_ra_serf__stat(svn_ra_session_t *ra_session,
- const char *relpath,
+ const char *repos_relpath,
svn_revnum_t revision,
svn_dirent_t **dirent,
apr_pool_t *pool)
@@ -239,29 +238,28 @@ svn_ra_serf__stat(svn_ra_session_t *ra_s
struct fill_dirent_baton_t fdb;
svn_tristate_t deadprop_count = svn_tristate_unknown;
svn_ra_serf__handler_t *handler;
- const char *url;
-
- url = session->session_url.path;
-
- /* If we have a relative path, append it. */
- if (relpath)
- url = svn_path_url_add_component2(url, relpath, pool);
+ const char *path;
/* If we were given a specific revision, get a URL that refers to that
specific revision (rather than floating with HEAD). */
if (SVN_IS_VALID_REVNUM(revision))
{
- SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */,
- session,
- url, revision,
- pool, pool));
+ SVN_ERR(svn_ra_serf__get_stable_url2(&path, NULL /* latest_revnum */,
+ session,
+ repos_relpath, revision,
+ pool, pool));
+ }
+ else
+ {
+ SVN_ERR(svn_ra_serf__resolve_path(ra_session, &path, repos_relpath,
+ pool));
}
fdb.entry = svn_dirent_create(pool);
fdb.supports_deadprop_count = &deadprop_count;
fdb.result_pool = pool;
- SVN_ERR(svn_ra_serf__create_propfind_handler(&handler, session, url,
+ SVN_ERR(svn_ra_serf__create_propfind_handler(&handler, session, path,
SVN_INVALID_REVNUM, "0",
get_dirent_props(SVN_DIRENT_ALL,
session,
@@ -408,7 +406,7 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
apr_hash_t **dirents,
svn_revnum_t *fetched_rev,
apr_hash_t **ret_props,
- const char *rel_path,
+ const char *repos_relpath,
svn_revnum_t revision,
apr_uint32_t dirent_fields,
apr_pool_t *result_pool)
@@ -425,25 +423,24 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
gdb.is_directory = FALSE;
gdb.supports_deadprop_count = svn_tristate_unknown;
- path = session->session_url.path;
-
- /* If we have a relative path, URI encode and append it. */
- if (rel_path)
- {
- path = svn_path_url_add_component2(path, rel_path, scratch_pool);
- }
/* If the user specified a peg revision other than HEAD, we have to fetch
the baseline collection url for that revision. If not, we can use the
public url. */
if (SVN_IS_VALID_REVNUM(revision) || fetched_rev)
{
- SVN_ERR(svn_ra_serf__get_stable_url(&path, fetched_rev,
- session,
- path, revision,
- scratch_pool, scratch_pool));
+ SVN_ERR(svn_ra_serf__get_stable_url2(&path, fetched_rev,
+ session,
+ repos_relpath, revision,
+ scratch_pool, scratch_pool));
revision = SVN_INVALID_REVNUM;
}
+ else
+ {
+ SVN_ERR(svn_ra_serf__resolve_path(ra_session, &path, repos_relpath,
+ scratch_pool));
+ }
+
/* REVISION is always SVN_INVALID_REVNUM */
SVN_ERR_ASSERT(!SVN_IS_VALID_REVNUM(revision));
Modified: subversion/branches/reparentless/subversion/libsvn_ra_serf/util.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_serf/util.c Fri Sep
4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra_serf/util.c Fri Sep
4 10:56:01 2026 (r1937857)
@@ -2052,6 +2052,30 @@ svn_ra_serf__uri_parse(apr_uri_t *uri,
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_ra_serf__resolve_path(svn_ra_session_t *ra_session,
+ const char **path,
+ const char *repos_relpath,
+ apr_pool_t *pool)
+{
+ svn_ra_serf__session_t *session = ra_session->priv;
+ apr_uri_t parsed;
+
+ if (! session->repos_root_str)
+ {
+ const char *vcc_url;
+ SVN_ERR(svn_ra_serf__discover_vcc(&vcc_url, session, pool));
+ }
+
+ SVN_ERR(svn_ra_serf__uri_parse(&parsed, session->repos_root_str, pool));
+
+ *path = svn_urlpath__canonicalize(svn_urlpath__join(parsed.path,
+ repos_relpath,
+ pool),
+ pool);
+ return SVN_NO_ERROR;
+}
+
void
svn_ra_serf__setup_svndiff_accept_encoding(serf_bucket_t *headers,
svn_ra_serf__session_t *session)
Modified: subversion/branches/reparentless/subversion/libsvn_ra_svn/client.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_svn/client.c Fri Sep
4 10:29:29 2026 (r1937856)
+++ subversion/branches/reparentless/subversion/libsvn_ra_svn/client.c Fri Sep
4 10:56:01 2026 (r1937857)
@@ -1014,6 +1014,43 @@ reparent_path(svn_ra_session_t *ra_sessi
return svn_relpath_join(parent->path->data, path, result_pool);
}
+/* Returns tweaked and reparented path from URL. */
+static svn_error_t *
+reparent_repos_relpath(const char **path_p,
+ svn_ra_session_t *ra_session,
+ const char *repos_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_ra_svn__session_baton_t *sess = ra_session->priv;
+ svn_ra_svn_conn_t *conn = sess->conn;
+ svn_ra_svn__parent_t *parent = sess->parent;
+ const char *relative_to_server, *url;
+
+ if (! conn->repos_root)
+ return svn_error_create(SVN_ERR_RA_SVN_BAD_VERSION, NULL,
+ _("Server did not send repository root"));
+
+ url = svn_path_url_add_component2(conn->repos_root, repos_relpath,
+ scratch_pool);
+
+ relative_to_server = svn_uri_skip_ancestor(parent->server_url->data,
+ url, scratch_pool);
+
+ if (! relative_to_server)
+ {
+ SVN_ERR(reparent_server(ra_session, url, scratch_pool));
+
+ relative_to_server = svn_uri_skip_ancestor(parent->server_url->data,
+ url, result_pool);
+
+ SVN_ERR_ASSERT(relative_to_server != NULL);
+ }
+
+ *path_p = apr_pstrdup(result_pool, relative_to_server);
+ return SVN_NO_ERROR;
+}
+
/* Return a copy of PATHS, containing the same const char * paths but
adjusted to the RA_SESSION's server parent URL. Returns NULL if
PATHS is NULL. Allocate the result in RESULT_POOL. */
@@ -1549,7 +1586,7 @@ static svn_error_t *ra_svn_get_dir(svn_r
apr_hash_t **dirents,
svn_revnum_t *fetched_rev,
apr_hash_t **props,
- const char *path,
+ const char *repos_relpath,
svn_revnum_t rev,
apr_uint32_t dirent_fields,
apr_pool_t *pool)
@@ -1557,9 +1594,11 @@ static svn_error_t *ra_svn_get_dir(svn_r
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_ra_svn__list_t *proplist, *dirlist;
+ const char *path;
int i;
- path = reparent_path(session, path, pool);
+ SVN_ERR(reparent_repos_relpath(&path, session, repos_relpath, pool, pool));
+
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(c(?r)bb(!", "get-dir", path,
rev, (props != NULL), (dirents != NULL)));
SVN_ERR(send_dirent_fields(conn, dirent_fields, pool));
@@ -2111,14 +2150,15 @@ ra_svn_log(svn_ra_session_t *session,
static svn_error_t *ra_svn_check_path(svn_ra_session_t *session,
- const char *path, svn_revnum_t rev,
+ const char *repos_relpath, svn_revnum_t
rev,
svn_node_kind_t *kind, apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
const char *kind_word;
+ const char *path;
- path = reparent_path(session, path, pool);
+ SVN_ERR(reparent_repos_relpath(&path, session, repos_relpath, pool, pool));
SVN_ERR(svn_ra_svn__write_cmd_check_path(conn, pool, path, rev));
SVN_ERR(handle_auth_request(sess_baton, pool));
SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "w", &kind_word));
@@ -2140,15 +2180,16 @@ static svn_error_t *handle_unsupported_c
static svn_error_t *ra_svn_stat(svn_ra_session_t *session,
- const char *path, svn_revnum_t rev,
+ const char *repos_relpath, svn_revnum_t rev,
svn_dirent_t **dirent, apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
svn_ra_svn__list_t *list = NULL;
svn_dirent_t *the_dirent;
+ const char *path;
- path = reparent_path(session, path, pool);
+ SVN_ERR(reparent_repos_relpath(&path, session, repos_relpath, pool, pool));
SVN_ERR(svn_ra_svn__write_cmd_stat(conn, pool, path, rev));
SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool),
N_("'stat' not implemented")));