Author: rhuijben
Date: Fri Dec 13 23:04:11 2013
New Revision: 1550848

URL: http://svn.apache.org/r1550848
Log:
Allow gracefull handling of the case where an 'mtcc' is opened on a file or
not existing node, by automatically reparenting one level up when allowed.

* subversion/include/svn_client.h
  (svn_client_mtcc_create): Update api to allow anchoring higher.
  (svn_client_mtcc_get_relpath): Update api to allow anchoring higher.

* subversion/libsvn_client/mtcc.c
  (svn_client_mtcc_create): Check if the anchor exist and handle the case where
    it doesn't.
  (svn_client_mtcc_get_relpath): Allow requesting at least one level higher than
    the passed url. (needed for things like mkdir)

* subversion/tests/libsvn_client/mtcc-test.c
  (make_greek_tree,
   test_mkdir,
   test_mkgreek,
   test_swap,
   test_propset,
   test_update_files,
   test_overwrite): Update caller.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/libsvn_client/mtcc.c
    subversion/trunk/subversion/tests/libsvn_client/mtcc-test.c

Modified: subversion/trunk/subversion/include/svn_client.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1550848&r1=1550847&r2=1550848&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Fri Dec 13 23:04:11 2013
@@ -6673,6 +6673,10 @@ typedef struct svn_client_mtcc_t svn_cli
 /** Creates a new multicommand context for an operation on @a anchor_url and
  * its descendants.
  *
+ * If @a anchor_url does not specify an existing directory returns an
+ * SVN_ERR_FS_NOT_DIRECTORY error, except when new_anchor_url is not NULL, and
+ * the mtcc can be rooted on an ancestor.
+ *
  * Allocate the context in @a result_pool and perform temporary allocations in
  * @a scratch_pool.
  *
@@ -6680,6 +6684,7 @@ typedef struct svn_client_mtcc_t svn_cli
  */
 svn_error_t *
 svn_client_mtcc_create(svn_client_mtcc_t **mtcc,
+                       const char **new_anchor_url,
                        const char *anchor_url,
                        svn_revnum_t base_revision,
                        svn_client_ctx_t *ctx,
@@ -6694,6 +6699,7 @@ svn_client_mtcc_create(svn_client_mtcc_t
 svn_error_t *
 svn_client_mtcc_get_relpath(const char **relpath,
                             const char *url,
+                            svn_boolean_t need_anchor,
                             svn_client_mtcc_t *mtcc,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);

Modified: subversion/trunk/subversion/libsvn_client/mtcc.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mtcc.c?rev=1550848&r1=1550847&r2=1550848&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mtcc.c (original)
+++ subversion/trunk/subversion/libsvn_client/mtcc.c Fri Dec 13 23:04:11 2013
@@ -236,6 +236,7 @@ svn_client_mtcc_get_origin(const char **
 
 svn_error_t *
 svn_client_mtcc_create(svn_client_mtcc_t **mtcc,
+                       const char **new_anchor_url,
                        const char *anchor_url,
                        svn_revnum_t base_revision,
                        svn_client_ctx_t *ctx,
@@ -243,6 +244,10 @@ svn_client_mtcc_create(svn_client_mtcc_t
                        apr_pool_t *scratch_pool)
 {
   apr_pool_t *mtcc_pool;
+  svn_node_kind_t kind;
+
+  if (new_anchor_url)
+    *new_anchor_url = NULL;
 
   mtcc_pool = svn_pool_create(result_pool);
 
@@ -258,6 +263,26 @@ svn_client_mtcc_create(svn_client_mtcc_t
                                       NULL /* wri_abspath */, ctx,
                                       mtcc_pool, scratch_pool));
 
+  SVN_ERR(svn_ra_check_path((*mtcc)->ra_session, "", base_revision, &kind,
+                            scratch_pool));
+
+  if (kind != svn_node_dir)
+    {
+      if (!new_anchor_url)
+        {
+          svn_pool_clear(mtcc_pool);
+          *mtcc = NULL;
+          return svn_error_createf(SVN_ERR_FS_NOT_DIRECTORY, NULL,
+                                   _("Can't open session on '%s' because "
+                                     "it is not a directory."),
+                                   anchor_url);
+        }
+
+      *new_anchor_url = svn_uri_dirname(anchor_url, result_pool);
+      SVN_ERR(svn_ra_reparent((*mtcc)->ra_session, *new_anchor_url,
+                              scratch_pool));
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -290,6 +315,7 @@ update_copy_src(svn_client_mtcc_op_t *op
 svn_error_t *
 svn_client_mtcc_get_relpath(const char **relpath,
                             const char *url,
+                            svn_boolean_t need_anchor,
                             svn_client_mtcc_t *mtcc,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
@@ -302,7 +328,9 @@ svn_client_mtcc_get_relpath(const char *
   err = svn_ra_get_path_relative_to_session(mtcc->ra_session, relpath, url,
                                             result_pool);
 
-  if (! err || err->apr_err != SVN_ERR_RA_ILLEGAL_URL)
+  if (! err && (*relpath || !need_anchor))
+    return SVN_NO_ERROR;
+  if (err && err->apr_err != SVN_ERR_RA_ILLEGAL_URL)
     return svn_error_trace(err);
 
   svn_error_clear(err);
@@ -310,7 +338,10 @@ svn_client_mtcc_get_relpath(const char *
   SVN_ERR(svn_ra_get_session_url(mtcc->ra_session, &session_url,
                                  scratch_pool));
 
-  new_anchor = svn_uri_get_longest_ancestor(url, session_url, scratch_pool);
+  if (!err && !*relpath && need_anchor)
+    new_anchor = svn_uri_dirname(session_url, scratch_pool);
+  else
+    new_anchor = svn_uri_get_longest_ancestor(url, session_url, scratch_pool);
 
   if (svn_path_is_empty(new_anchor))
     {

Modified: subversion/trunk/subversion/tests/libsvn_client/mtcc-test.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/libsvn_client/mtcc-test.c?rev=1550848&r1=1550847&r2=1550848&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/mtcc-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/mtcc-test.c Fri Dec 13 
23:04:11 2013
@@ -84,7 +84,7 @@ make_greek_tree(const char *repos_url,
   subpool = svn_pool_create(scratch_pool);
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, subpool));
-  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 0, ctx, subpool, subpool));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, NULL, repos_url, 0, ctx, subpool, 
subpool));
 
   for (i = 0; svn_test__greek_tree_nodes[i].path; i++)
     {
@@ -130,7 +130,7 @@ test_mkdir(const svn_test_opts_t *opts,
   SVN_ERR(svn_test__create_repos(&repos, repos_abspath, opts, pool));
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
-  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 0, ctx, pool, pool));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, NULL, repos_url, 0, ctx, pool, pool));
 
   SVN_ERR(svn_client_mtcc_add_mkdir("branches", mtcc, pool));
   SVN_ERR(svn_client_mtcc_add_mkdir("trunk", mtcc, pool));
@@ -162,7 +162,7 @@ test_mkgreek(const svn_test_opts_t *opts
   SVN_ERR(make_greek_tree(repos_url, pool));
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
-  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 1, ctx, pool, pool));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, NULL, repos_url, 1, ctx, pool, pool));
 
   SVN_ERR(svn_client_mtcc_add_copy("A", 1, "greek_A", mtcc, pool));
 
@@ -189,7 +189,7 @@ test_swap(const svn_test_opts_t *opts,
   SVN_ERR(make_greek_tree(repos_url, pool));
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
-  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 1, ctx, pool, pool));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, NULL, repos_url, 1, ctx, pool, pool));
 
   SVN_ERR(svn_client_mtcc_add_move("A/B", "B", mtcc, pool));
   SVN_ERR(svn_client_mtcc_add_move("A/D", "A/B", mtcc, pool));
@@ -218,7 +218,7 @@ test_propset(const svn_test_opts_t *opts
   SVN_ERR(make_greek_tree(repos_url, pool));
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
-  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 1, ctx, pool, pool));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, NULL, repos_url, 1, ctx, pool, pool));
 
   SVN_ERR(svn_client_mtcc_add_propset("iota", "key",
                                       svn_string_create("val", pool), FALSE,
@@ -257,7 +257,7 @@ test_update_files(const svn_test_opts_t 
   SVN_ERR(make_greek_tree(repos_url, pool));
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
-  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 1, ctx, pool, pool));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, NULL, repos_url, 1, ctx, pool, pool));
 
   /* Update iota with knowledge of the old data */
   SVN_ERR(svn_client_mtcc_add_update_file(svn_test__greek_tree_nodes[0].path,
@@ -315,7 +315,7 @@ test_overwrite(const svn_test_opts_t *op
   SVN_ERR(make_greek_tree(repos_url, pool));
 
   SVN_ERR(svn_client_create_context2(&ctx, NULL, pool));
-  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 1, ctx, pool, pool));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, NULL, repos_url, 1, ctx, pool, pool));
 
   SVN_ERR(svn_client_mtcc_add_copy("A", 1, "AA", mtcc, pool));
 


Reply via email to