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")));

Reply via email to