Author: rhuijben
Date: Sun Dec 15 23:49:12 2013
New Revision: 1551085

URL: http://svn.apache.org/r1551085
Log:
Implement the full 'svn:*' property validation and conicalization for 'svnmucc'
in the mtcc api.

* subversion/libsvn_client/mtcc.c
  (get_origin): If a node is added and has no recorded origin, report the
    node as without origin.
  (mtcc_prop_get_baton): New struct.
  (mtcc_prop_getter): New function.
  (svn_client_mtcc_add_propset): Use the result of svn_subst_translate_string2
    instead of ignoring it. Call svn_wc_canonicalize_svn_prop() for further
    canonicalizations and verifications.

* subversion/tests/libsvn_client/mtcc-test.c
  (includes): Add svn_props.h.
  (test_propset): Extend testcase with some explicit failure cases.

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

Modified: subversion/trunk/subversion/libsvn_client/mtcc.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/mtcc.c?rev=1551085&r1=1551084&r2=1551085&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/mtcc.c (original)
+++ subversion/trunk/subversion/libsvn_client/mtcc.c Sun Dec 15 23:49:12 2013
@@ -174,6 +174,8 @@ get_origin(svn_boolean_t *done,
   const char *name;
   if (SVN_PATH_IS_EMPTY(relpath))
     {
+      if (op->kind == OP_ADD_DIR || op->kind == OP_ADD_FILE)
+        *done = TRUE;
       *origin_relpath = op->src_relpath
                                 ? apr_pstrdup(result_pool, op->src_relpath)
                                 : NULL;
@@ -612,6 +614,103 @@ svn_client_mtcc_add_move(const char *src
   return SVN_NO_ERROR;
 }
 
+/* Baton for mtcc_prop_getter */
+struct mtcc_prop_get_baton
+{
+  svn_client_mtcc_t *mtcc;
+  const char *relpath;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+};
+
+/* Implements svn_wc_canonicalize_svn_prop_get_file_t */
+static svn_error_t *
+mtcc_prop_getter(const svn_string_t **mime_type,
+                 svn_stream_t *stream,
+                 void *baton,
+                 apr_pool_t *pool)
+{
+  struct mtcc_prop_get_baton *mpgb = baton;
+  const char *origin_relpath;
+  svn_revnum_t origin_rev;
+  apr_hash_t *props = NULL;
+
+  svn_client_mtcc_op_t *op;
+
+  if (mime_type)
+    *mime_type = NULL;
+
+  /* Check if we have the information locally */
+  SVN_ERR(mtcc_op_find(&op, NULL, mpgb->relpath, mpgb->mtcc->root_op, TRUE,
+                       FALSE, FALSE, pool, pool));
+
+  if (op)
+    {
+      if (mime_type)
+        {
+          int i;
+
+          for (i = 0; op->prop_mods && i < op->prop_mods->nelts; i++)
+            {
+              const svn_prop_t *mod = &APR_ARRAY_IDX(op->prop_mods, i,
+                                                     svn_prop_t);
+
+              if (! strcmp(mod->name, SVN_PROP_MIME_TYPE))
+                {
+                  *mime_type = mod->value ? svn_string_dup(mod->value, pool)
+                                          : NULL;
+                  mime_type = NULL;
+                }
+            }
+        }
+
+      if (stream && op->src_stream)
+        {
+          svn_stream_mark_t *mark;
+          svn_error_t *err;
+
+          /* Is the source stream capable of being read multiple times? */
+          err = svn_stream_mark(op->src_stream, &mark, pool);
+
+          if (err && err->apr_err != SVN_ERR_STREAM_SEEK_NOT_SUPPORTED)
+            return svn_error_trace(err);
+          svn_error_clear(err);
+
+          if (!err)
+            {
+              err = svn_stream_copy3(svn_stream_disown(op->src_stream, pool),
+                                     svn_stream_disown(stream, pool),
+                                     mpgb->cancel_func, mpgb->cancel_baton,
+                                     pool);
+
+              SVN_ERR(svn_error_compose_create(
+                            err,
+                            svn_stream_seek(op->src_stream, mark)));
+            }
+          /* else: ### Create tempfile? */
+
+          stream = NULL; /* Stream is handled */
+        }
+    }
+
+  if (!stream && !mime_type)
+    return SVN_NO_ERROR;
+
+  SVN_ERR(mtcc_get_origin(&origin_relpath, &origin_rev, mpgb->relpath, TRUE,
+                          mpgb->mtcc, pool, pool));
+
+  if (!origin_relpath)
+    return SVN_NO_ERROR; /* Nothing to fetch at repository */
+
+  SVN_ERR(svn_ra_get_file(mpgb->mtcc->ra_session, origin_relpath, origin_rev,
+                          stream, NULL, mime_type ? &props : NULL, pool));
+
+  if (mime_type && props)
+    *mime_type = svn_hash_gets(props, SVN_PROP_MIME_TYPE);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_client_mtcc_add_propset(const char *relpath,
                             const char *propname,
@@ -640,16 +739,31 @@ svn_client_mtcc_add_propset(const char *
   if (!skip_checks && svn_prop_needs_translation(propname))
     {
       svn_string_t *translated_value;
-       SVN_ERR_W(svn_subst_translate_string2(&translated_value, NULL,
-                                             NULL, propval,
-                                             NULL, FALSE,
-                                             scratch_pool, scratch_pool),
-                 _("Error normalizing property value"));
+      SVN_ERR_W(svn_subst_translate_string2(&translated_value, NULL,
+                                            NULL, propval,
+                                            NULL, FALSE,
+                                            scratch_pool, scratch_pool),
+                _("Error normalizing property value"));
+
+      propval = translated_value;
     }
 
   if (propval && svn_prop_is_svn_prop(propname))
     {
-      /* ### TODO: Call svn_wc_canonicalize_svn_prop() */
+      struct mtcc_prop_get_baton mpbg;
+      svn_node_kind_t kind;
+      SVN_ERR(svn_client_mtcc_check_path(&kind, relpath, FALSE, mtcc,
+                                         scratch_pool));
+
+      mpbg.mtcc = mtcc;
+      mpbg.relpath = relpath;
+      mpbg.cancel_func = mtcc->ctx->cancel_func;
+      mpbg.cancel_baton = mtcc->ctx->cancel_baton;
+
+      SVN_ERR(svn_wc_canonicalize_svn_prop(&propval, propname, propval,
+                                           relpath, kind, skip_checks,
+                                           mtcc_prop_getter, &mpbg,
+                                           scratch_pool));
     }
 
   if (SVN_PATH_IS_EMPTY(relpath) && MTCC_UNMODIFIED(mtcc))

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=1551085&r1=1551084&r2=1551085&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/libsvn_client/mtcc-test.c (original)
+++ subversion/trunk/subversion/tests/libsvn_client/mtcc-test.c Sun Dec 15 
23:49:12 2013
@@ -25,6 +25,7 @@
 
 #include "svn_mergeinfo.h"
 #include "svn_pools.h"
+#include "svn_props.h"
 #include "svn_client.h"
 #include "svn_repos.h"
 #include "svn_subst.h"
@@ -241,6 +242,41 @@ test_propset(const svn_test_opts_t *opts
                                       mtcc, pool));
 
   SVN_ERR(verify_mtcc_commit(mtcc, 2, pool));
+
+  SVN_ERR(svn_client_mtcc_create(&mtcc, repos_url, 2, ctx, pool, pool));
+  SVN_TEST_ASSERT_ERROR(
+      svn_client_mtcc_add_propset("A", SVN_PROP_MIME_TYPE,
+                                  svn_string_create("text/plain", pool),
+                                  FALSE, mtcc, pool),
+      SVN_ERR_ILLEGAL_TARGET);
+
+  SVN_TEST_ASSERT_ERROR(
+      svn_client_mtcc_add_propset("iota", SVN_PROP_IGNORE,
+                                  svn_string_create("iota", pool),
+                                  FALSE, mtcc, pool),
+      SVN_ERR_ILLEGAL_TARGET);
+
+  SVN_ERR(svn_client_mtcc_add_propset("iota", SVN_PROP_EOL_STYLE,
+                                      svn_string_create("LF", pool),
+                                      FALSE, mtcc, pool));
+
+  SVN_ERR(svn_client_mtcc_add_add_file("ok", cstr_stream("line\nline\n", pool),
+                                       NULL, mtcc, pool));
+  SVN_ERR(svn_client_mtcc_add_add_file("bad", cstr_stream("line\nno\r\n", 
pool),
+                                       NULL, mtcc, pool));
+
+  SVN_ERR(svn_client_mtcc_add_propset("ok", SVN_PROP_EOL_STYLE,
+                                      svn_string_create("LF", pool),
+                                      FALSE, mtcc, pool));
+
+  SVN_TEST_ASSERT_ERROR(
+          svn_client_mtcc_add_propset("bad", SVN_PROP_EOL_STYLE,
+                                      svn_string_create("LF", pool),
+                                      FALSE, mtcc, pool),
+          SVN_ERR_ILLEGAL_TARGET);
+
+  SVN_ERR(verify_mtcc_commit(mtcc, 3, pool));
+
   return SVN_NO_ERROR;
 }
 


Reply via email to