Author: rinrab
Date: Fri Sep 25 17:57:10 2026
New Revision: 1938518

Log:
On the 'reparentless' branch: Implement lock-unlock operations by
repos_relpath.

* subversion/include/svn_ra.h
  (svn_ra_lock2, svn_ra_unlock2): Declare.
  (svn_ra_lock, svn_ra_unlock): Deprecate.
* subversion/libsvn_ra/deprecated.c
  (svn_ra_lock, svn_ra_unlock): Implement compat wrappers.
* subversion/libsvn_ra/ra_loader.c
  (svn_ra_lock2, svn_ra_unlock2): Update version.
* subversion/libsvn_ra_local/ra_plugin.c
  (svn_ra_local__lock, svn_ra_local__unlock): Assume absolute paths.
* subversion/libsvn_ra_svn/client.c 
  (reparent_repos_relpath_hash): New function - substitute for
   reparent_path_hash.
  (reparent_path_hash): Delete.
  (ra_svn_lock, ra_svn_unlock): Use new function for reparenting path
   collection.

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_local/ra_plugin.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 
25 16:52:04 2026        (r1938517)
+++ subversion/branches/reparentless/subversion/include/svn_ra.h        Fri Sep 
25 17:57:10 2026        (r1938518)
@@ -2191,7 +2191,24 @@ svn_ra_get_file_revs(svn_ra_session_t *s
  *
  * Use @a pool for temporary allocations.
  *
+ * @since New in 1.16.
+ */
+svn_error_t *
+svn_ra_lock2(svn_ra_session_t *session,
+             apr_hash_t *path_revs,
+             const char *comment,
+             svn_boolean_t steal_lock,
+             svn_ra_lock_callback_t lock_func,
+             void *lock_baton,
+             apr_pool_t *pool);
+
+
+/**
+ * Similar to @c svn_ra_lock, but @a path_revs specify paths relative to
+ * session URL.
+ *
  * @since New in 1.2.
+ * @deprecated Provided for compatibility with the 1.15 API.
  */
 svn_error_t *
 svn_ra_lock(svn_ra_session_t *session,
@@ -2223,7 +2240,23 @@ svn_ra_lock(svn_ra_session_t *session,
  *
  * Use @a pool for temporary allocations.
  *
+ * @since New in 1.16.
+ */
+svn_error_t *
+svn_ra_unlock2(svn_ra_session_t *session,
+               apr_hash_t *path_tokens,
+               svn_boolean_t break_lock,
+               svn_ra_lock_callback_t lock_func,
+               void *lock_baton,
+               apr_pool_t *pool);
+
+
+/**
+ * Similar to @c svn_ra_unlock, but @a path_tokens specify paths relative to
+ * session URL.
+ *
  * @since New in 1.2.
+ * @deprecated Provided for compatibility with the 1.15 API.
  */
 svn_error_t *
 svn_ra_unlock(svn_ra_session_t *session,

Modified: subversion/branches/reparentless/subversion/libsvn_ra/deprecated.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra/deprecated.c  Fri Sep 
25 16:52:04 2026        (r1938517)
+++ subversion/branches/reparentless/subversion/libsvn_ra/deprecated.c  Fri Sep 
25 17:57:10 2026        (r1938518)
@@ -494,6 +494,71 @@ svn_ra_get_locks2(svn_ra_session_t *sess
 }
 
 svn_error_t *
+svn_ra_lock(svn_ra_session_t *session,
+            apr_hash_t *path_revs,
+            const char *comment,
+            svn_boolean_t steal_lock,
+            svn_ra_lock_callback_t lock_func,
+            void *lock_baton,
+            apr_pool_t *pool)
+{
+  apr_hash_t *abs_path_revs = apr_hash_make(pool);
+  apr_hash_index_t *hi;
+  const char *session_path;
+
+  SVN_ERR(get_session_path(session, &session_path, pool));
+
+  for (hi = apr_hash_first(pool, path_revs);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *path = apr_hash_this_key(hi);
+      const char *value = apr_hash_this_val(hi);
+
+      svn_hash_sets(abs_path_revs,
+                    svn_relpath_join(session_path, path, pool),
+                    value);
+    }
+
+  SVN_ERR(svn_ra_lock2(session, abs_path_revs, comment, steal_lock, lock_func,
+                       lock_baton, pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_ra_unlock(svn_ra_session_t *session,
+              apr_hash_t *path_tokens,
+              svn_boolean_t break_lock,
+              svn_ra_lock_callback_t lock_func,
+              void *lock_baton,
+              apr_pool_t *pool)
+{
+  apr_hash_t *abs_path_tokens = apr_hash_make(pool);
+  apr_hash_index_t *hi;
+  const char *session_path;
+
+  SVN_ERR(get_session_path(session, &session_path, pool));
+
+  for (hi = apr_hash_first(pool, path_tokens);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *path = apr_hash_this_key(hi);
+      const char *value = apr_hash_this_val(hi);
+
+      svn_hash_sets(abs_path_tokens,
+                    svn_relpath_join(session_path, path, pool),
+                    value);
+    }
+
+  SVN_ERR(svn_ra_unlock2(session, abs_path_tokens, break_lock, lock_func,
+                         lock_baton, pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_ra_do_update3(svn_ra_session_t *session,
                   const svn_ra_reporter3_t **reporter,
                   void **report_baton,

Modified: subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.c   Fri Sep 
25 16:52:04 2026        (r1938517)
+++ subversion/branches/reparentless/subversion/libsvn_ra/ra_loader.c   Fri Sep 
25 17:57:10 2026        (r1938518)
@@ -1089,13 +1089,13 @@ svn_error_t *svn_ra_get_file_revs3(svn_r
   return svn_error_trace(err);
 }
 
-svn_error_t *svn_ra_lock(svn_ra_session_t *session,
-                         apr_hash_t *path_revs,
-                         const char *comment,
-                         svn_boolean_t steal_lock,
-                         svn_ra_lock_callback_t lock_func,
-                         void *lock_baton,
-                         apr_pool_t *pool)
+svn_error_t *svn_ra_lock2(svn_ra_session_t *session,
+                          apr_hash_t *path_revs,
+                          const char *comment,
+                          svn_boolean_t steal_lock,
+                          svn_ra_lock_callback_t lock_func,
+                          void *lock_baton,
+                          apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
 
@@ -1115,12 +1115,12 @@ svn_error_t *svn_ra_lock(svn_ra_session_
                                lock_func, lock_baton, pool);
 }
 
-svn_error_t *svn_ra_unlock(svn_ra_session_t *session,
-                           apr_hash_t *path_tokens,
-                           svn_boolean_t break_lock,
-                           svn_ra_lock_callback_t lock_func,
-                           void *lock_baton,
-                           apr_pool_t *pool)
+svn_error_t *svn_ra_unlock2(svn_ra_session_t *session,
+                            apr_hash_t *path_tokens,
+                            svn_boolean_t break_lock,
+                            svn_ra_lock_callback_t lock_func,
+                            void *lock_baton,
+                            apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
 

Modified: 
subversion/branches/reparentless/subversion/libsvn_ra_local/ra_plugin.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_local/ra_plugin.c     
Fri Sep 25 16:52:04 2026        (r1938517)
+++ subversion/branches/reparentless/subversion/libsvn_ra_local/ra_plugin.c     
Fri Sep 25 17:57:10 2026        (r1938518)
@@ -1523,7 +1523,7 @@ svn_ra_local__lock(svn_ra_session_t *ses
 
   for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi))
     {
-      const char *abs_path = svn_fspath__join(sess->fs_path->data,
+      const char *abs_path = svn_fspath__join("/",
                                               apr_hash_this_key(hi), pool);
       svn_revnum_t current_rev = *(svn_revnum_t *)apr_hash_this_val(hi);
       svn_fs_lock_target_t *target = svn_fs_lock_target_create(NULL,
@@ -1573,7 +1573,7 @@ svn_ra_local__unlock(svn_ra_session_t *s
 
   for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
     {
-      const char *abs_path = svn_fspath__join(sess->fs_path->data,
+      const char *abs_path = svn_fspath__join("/",
                                               apr_hash_this_key(hi), pool);
       const char *token = apr_hash_this_val(hi);
 

Modified: subversion/branches/reparentless/subversion/libsvn_ra_svn/client.c
==============================================================================
--- subversion/branches/reparentless/subversion/libsvn_ra_svn/client.c  Fri Sep 
25 16:52:04 2026        (r1938517)
+++ subversion/branches/reparentless/subversion/libsvn_ra_svn/client.c  Fri Sep 
25 17:57:10 2026        (r1938518)
@@ -1078,6 +1078,57 @@ reparent_repos_relpath_exact(svn_ra_sess
 
   return SVN_NO_ERROR;
 }
+
+static svn_error_t *
+reparent_repos_relpath_hash(svn_ra_session_t *ra_session,
+                            apr_hash_t *paths,
+                            apr_hash_t *result,
+                            apr_pool_t *scratch_pool,
+                            apr_pool_t *result_pool)
+{
+  svn_ra_svn__session_baton_t *sess = ra_session->priv;
+  const char *common_ancestor = NULL;
+  const char *dummy, *reparented;
+  apr_hash_index_t *hi;
+
+  for (hi = apr_hash_first(scratch_pool, paths);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *path = apr_hash_this_key(hi);
+
+      if (common_ancestor)
+        common_ancestor = svn_relpath_get_longest_ancestor(common_ancestor,
+                                                           path, scratch_pool);
+      else
+        common_ancestor = path;
+    }
+
+
+  SVN_ERR(reparent_repos_relpath(&dummy, ra_session, common_ancestor,
+                                 scratch_pool, scratch_pool));
+
+  reparented = svn_uri_skip_ancestor(sess->conn->repos_root,
+                                     sess->parent->server_url->data,
+                                     result_pool);
+
+  for (hi = apr_hash_first(scratch_pool, paths);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *path, *newpath;
+
+      path = apr_hash_this_key(hi);
+      newpath = svn_relpath_skip_ancestor(reparented, path);
+
+      svn_hash_sets(result,
+                    apr_pstrdup(result_pool, newpath),
+                    apr_hash_this_val(hi));
+    }
+
+  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. */
@@ -1102,33 +1153,6 @@ reparent_path_array(svn_ra_session_t *ra
   return result;
 }
 
-/* Return a copy of PATHS, containing the same paths for keys but adjusted
-   to the RA_SESSION's server parent URL.  Keeps the values as-are and
-   returns NULL if PATHS is NULL.  Allocate the result in RESULT_POOL. */
-static apr_hash_t *
-reparent_path_hash(svn_ra_session_t *ra_session,
-                   apr_hash_t *paths,
-                   apr_pool_t *result_pool,
-                   apr_pool_t *scratch_pool)
-{
-  apr_hash_t *result;
-  apr_hash_index_t *hi;
-
-  if (!paths)
-    return NULL;
-
-  result = svn_hash__make(result_pool);
-  for (hi = apr_hash_first(scratch_pool, paths); hi; hi = apr_hash_next(hi))
-    {
-      const char *path = apr_hash_this_key(hi);
-      svn_hash_sets(result,
-                    reparent_path(ra_session, path, result_pool),
-                    apr_hash_this_val(hi));
-    }
-
-  return result;
-}
-
 static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session,
                                     const char *url,
                                     apr_pool_t *pool)
@@ -2683,15 +2707,17 @@ static svn_error_t *ra_svn_lock(svn_ra_s
 {
   svn_ra_svn__session_baton_t *sess = session->priv;
   svn_ra_svn_conn_t *conn = sess->conn;
+  apr_hash_t *reparented = apr_hash_make(pool);
   apr_hash_index_t *hi;
   svn_error_t *err;
   apr_pool_t *iterpool = svn_pool_create(pool);
 
-  path_revs = reparent_path_hash(session, path_revs, pool, pool);
+  SVN_ERR(reparent_repos_relpath_hash(session, path_revs, reparented,
+                                      pool, pool));
   SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((?c)b(!", "lock-many",
                                   comment, steal_lock));
 
-  for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(pool, reparented); hi; hi = apr_hash_next(hi))
     {
       const void *key;
       const char *path;
@@ -2715,7 +2741,7 @@ static svn_error_t *ra_svn_lock(svn_ra_s
   if (err && err->apr_err == SVN_ERR_RA_SVN_UNKNOWN_CMD)
     {
       svn_error_clear(err);
-      return ra_svn_lock_compat(session, path_revs, comment, steal_lock,
+      return ra_svn_lock_compat(session, reparented, comment, steal_lock,
                                 lock_func, lock_baton, pool);
     }
 
@@ -2723,7 +2749,7 @@ static svn_error_t *ra_svn_lock(svn_ra_s
     return err;
 
   /* Loop over responses to get lock information. */
-  for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(pool, reparented); hi; hi = apr_hash_next(hi))
     {
       svn_ra_svn__item_t *elt;
       const void *key;
@@ -2807,16 +2833,18 @@ static svn_error_t *ra_svn_unlock(svn_ra
 {
   svn_ra_svn__session_baton_t *sess = session->priv;
   svn_ra_svn_conn_t *conn = sess->conn;
+  apr_hash_t *reparented = apr_hash_make(pool);
   apr_hash_index_t *hi;
   apr_pool_t *iterpool = svn_pool_create(pool);
   svn_error_t *err;
   const char *path;
 
-  path_tokens = reparent_path_hash(session, path_tokens, pool, pool);
+  SVN_ERR(reparent_repos_relpath_hash(session, path_tokens, reparented,
+                                      pool, pool));
   SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(b(!", "unlock-many",
                                   break_lock));
 
-  for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(pool, reparented); hi; hi = apr_hash_next(hi))
     {
       void *val;
       const void *key;
@@ -2844,7 +2872,7 @@ static svn_error_t *ra_svn_unlock(svn_ra
   if (err && err->apr_err == SVN_ERR_RA_SVN_UNKNOWN_CMD)
     {
       svn_error_clear(err);
-      return ra_svn_unlock_compat(session, path_tokens, break_lock, lock_func,
+      return ra_svn_unlock_compat(session, reparented, break_lock, lock_func,
                                   lock_baton, pool);
     }
 
@@ -2852,7 +2880,7 @@ static svn_error_t *ra_svn_unlock(svn_ra
     return err;
 
   /* Loop over responses to unlock files. */
-  for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(pool, reparented); hi; hi = apr_hash_next(hi))
     {
       svn_ra_svn__item_t *elt;
       const void *key;

Reply via email to