subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1550968 - in /subversion/trunk/subversion: svnmucc/svnmucc.c tests/cmdline/svnmucc_tests.py
Date Sat, 14 Dec 2013 20:45:12 GMT
Author: rhuijben
Date: Sat Dec 14 20:45:12 2013
New Revision: 1550968

URL: http://svn.apache.org/r1550968
Log:
Start using the 'mtcc' api from svnmucc, removing about 30% of the code from
svnmucc.

* subversion/svnmucc/svnmucc.c
  (operation): Remove struct.
  (change_props,
   drive,
   get_operation,
   build): Remove function.

  (execute): Remove unused argument. Build operation using the mtcc api. Use
    iterpool pattern. Remove log message logic.

  (log_message_baton): New struct.
  (log_message_func): New function.
  (sub_main): Setup svn_client_ctx_t log message handling. Update caller.

* subversion/tests/cmdline/svnmucc_tests.py
  (basic_svnmucc): Expect slightly different error codes for certain error
    conditions.

Modified:
    subversion/trunk/subversion/svnmucc/svnmucc.c
    subversion/trunk/subversion/tests/cmdline/svnmucc_tests.py

Modified: subversion/trunk/subversion/svnmucc/svnmucc.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svnmucc/svnmucc.c?rev=1550968&r1=1550967&r2=1550968&view=diff
==============================================================================
--- subversion/trunk/subversion/svnmucc/svnmucc.c (original)
+++ subversion/trunk/subversion/svnmucc/svnmucc.c Sat Dec 14 20:45:12 2013
@@ -99,204 +99,6 @@ typedef enum action_code_t {
   ACTION_RM
 } action_code_t;
 
-struct operation {
-  enum {
-    OP_OPEN,
-    OP_DELETE,
-    OP_ADD,
-    OP_REPLACE,
-    OP_PROPSET           /* only for files for which no other operation is
-                            occuring; directories are OP_OPEN with non-empty
-                            props */
-  } operation;
-  svn_node_kind_t kind;  /* to copy, mkdir, put or set revprops */
-  svn_revnum_t rev;      /* to copy, valid for add and replace */
-  const char *url;       /* to copy, valid for add and replace */
-  const char *src_file;  /* for put, the source file for contents */
-  apr_hash_t *children;  /* const char *path -> struct operation * */
-  apr_hash_t *prop_mods; /* const char *prop_name ->
-                            const svn_string_t *prop_value */
-  apr_array_header_t *prop_dels; /* const char *prop_name deletions */
-  void *baton;           /* as returned by the commit editor */
-};
-
-
-/* Set node properties.
-   ... */
-static svn_error_t *
-change_props(const svn_delta_editor_t *editor,
-             void *baton,
-             struct operation *child,
-             apr_pool_t *pool)
-{
-  apr_pool_t *iterpool = svn_pool_create(pool);
-
-  if (child->prop_dels)
-    {
-      int i;
-      for (i = 0; i < child->prop_dels->nelts; i++)
-        {
-          const char *prop_name;
-
-          svn_pool_clear(iterpool);
-          prop_name = APR_ARRAY_IDX(child->prop_dels, i, const char *);
-          if (child->kind == svn_node_dir)
-            SVN_ERR(editor->change_dir_prop(baton, prop_name,
-                                            NULL, iterpool));
-          else
-            SVN_ERR(editor->change_file_prop(baton, prop_name,
-                                             NULL, iterpool));
-        }
-    }
-  if (apr_hash_count(child->prop_mods))
-    {
-      apr_hash_index_t *hi;
-      for (hi = apr_hash_first(pool, child->prop_mods);
-           hi; hi = apr_hash_next(hi))
-        {
-          const char *propname = svn__apr_hash_index_key(hi);
-          const svn_string_t *val = svn__apr_hash_index_val(hi);
-
-          svn_pool_clear(iterpool);
-          if (child->kind == svn_node_dir)
-            SVN_ERR(editor->change_dir_prop(baton, propname, val, iterpool));
-          else
-            SVN_ERR(editor->change_file_prop(baton, propname, val, iterpool));
-        }
-    }
-
-  svn_pool_destroy(iterpool);
-  return SVN_NO_ERROR;
-}
-
-
-/* Drive EDITOR to affect the change represented by OPERATION.  HEAD
-   is the last-known youngest revision in the repository. */
-static svn_error_t *
-drive(struct operation *operation,
-      svn_revnum_t head,
-      const svn_delta_editor_t *editor,
-      apr_pool_t *pool)
-{
-  apr_pool_t *subpool = svn_pool_create(pool);
-  apr_hash_index_t *hi;
-
-  for (hi = apr_hash_first(pool, operation->children);
-       hi; hi = apr_hash_next(hi))
-    {
-      const char *key = svn__apr_hash_index_key(hi);
-      struct operation *child = svn__apr_hash_index_val(hi);
-      void *file_baton = NULL;
-
-      svn_pool_clear(subpool);
-
-      /* Deletes and replacements are simple -- delete something. */
-      if (child->operation == OP_DELETE || child->operation == OP_REPLACE)
-        {
-          SVN_ERR(editor->delete_entry(key, head, operation->baton, subpool));
-        }
-      /* Opens could be for directories or files. */
-      if (child->operation == OP_OPEN || child->operation == OP_PROPSET)
-        {
-          if (child->kind == svn_node_dir)
-            {
-              SVN_ERR(editor->open_directory(key, operation->baton, head,
-                                             subpool, &child->baton));
-            }
-          else
-            {
-              SVN_ERR(editor->open_file(key, operation->baton, head,
-                                        subpool, &file_baton));
-            }
-        }
-      /* Adds and replacements could also be for directories or files. */
-      if (child->operation == OP_ADD || child->operation == OP_REPLACE)
-        {
-          if (child->kind == svn_node_dir)
-            {
-              SVN_ERR(editor->add_directory(key, operation->baton,
-                                            child->url, child->rev,
-                                            subpool, &child->baton));
-            }
-          else
-            {
-              SVN_ERR(editor->add_file(key, operation->baton, child->url,
-                                       child->rev, subpool, &file_baton));
-            }
-        }
-      /* If there's a source file and an open file baton, we get to
-         change textual contents. */
-      if ((child->src_file) && (file_baton))
-        {
-          svn_txdelta_window_handler_t handler;
-          void *handler_baton;
-          svn_stream_t *contents;
-
-          SVN_ERR(editor->apply_textdelta(file_baton, NULL, subpool,
-                                          &handler, &handler_baton));
-          if (strcmp(child->src_file, "-") != 0)
-            {
-              SVN_ERR(svn_stream_open_readonly(&contents, child->src_file,
-                                               pool, pool));
-            }
-          else
-            {
-              SVN_ERR(svn_stream_for_stdin(&contents, pool));
-            }
-          SVN_ERR(svn_txdelta_send_stream(contents, handler,
-                                          handler_baton, NULL, pool));
-        }
-      /* If we opened a file, we need to apply outstanding propmods,
-         then close it. */
-      if (file_baton)
-        {
-          if (child->kind == svn_node_file)
-            {
-              SVN_ERR(change_props(editor, file_baton, child, subpool));
-            }
-          SVN_ERR(editor->close_file(file_baton, NULL, subpool));
-        }
-      /* If we opened, added, or replaced a directory, we need to
-         recurse, apply outstanding propmods, and then close it. */
-      if ((child->kind == svn_node_dir)
-          && child->operation != OP_DELETE)
-        {
-          SVN_ERR(change_props(editor, child->baton, child, subpool));
-
-          SVN_ERR(drive(child, head, editor, subpool));
-
-          SVN_ERR(editor->close_directory(child->baton, subpool));
-        }
-    }
-  svn_pool_destroy(subpool);
-  return SVN_NO_ERROR;
-}
-
-
-/* Find the operation associated with PATH, which is a single-path
-   component representing a child of the path represented by
-   OPERATION.  If no such child operation exists, create a new one of
-   type OP_OPEN. */
-static struct operation *
-get_operation(const char *path,
-              struct operation *operation,
-              apr_pool_t *pool)
-{
-  struct operation *child = svn_hash_gets(operation->children, path);
-  if (! child)
-    {
-      child = apr_pcalloc(pool, sizeof(*child));
-      child->children = apr_hash_make(pool);
-      child->operation = OP_OPEN;
-      child->rev = SVN_INVALID_REVNUM;
-      child->kind = svn_node_dir;
-      child->prop_mods = apr_hash_make(pool);
-      child->prop_dels = apr_array_make(pool, 1, sizeof(const char *));
-      svn_hash_sets(operation->children, path, child);
-    }
-  return child;
-}
-
 /* Return the portion of URL that is relative to ANCHOR (URI-decoded). */
 static const char *
 subtract_anchor(const char *anchor, const char *url, apr_pool_t *pool)
@@ -304,221 +106,6 @@ subtract_anchor(const char *anchor, cons
   return svn_uri_skip_ancestor(anchor, url, pool);
 }
 
-/* Add PATH to the operations tree rooted at OPERATION, creating any
-   intermediate nodes that are required.  Here's what's expected for
-   each action type:
-
-      ACTION          URL    REV      SRC-FILE  PROPNAME
-      ------------    -----  -------  --------  --------
-      ACTION_MKDIR    NULL   invalid  NULL      NULL
-      ACTION_CP       valid  valid    NULL      NULL
-      ACTION_PUT      NULL   invalid  valid     NULL
-      ACTION_RM       NULL   invalid  NULL      NULL
-      ACTION_PROPSET  valid  invalid  NULL      valid
-      ACTION_PROPDEL  valid  invalid  NULL      valid
-
-   Node type information is obtained for any copy source (to determine
-   whether to create a file or directory) and for any deleted path (to
-   ensure it exists since svn_delta_editor_t->delete_entry doesn't
-   return an error on non-existent nodes). */
-static svn_error_t *
-build(action_code_t action,
-      const char *path,
-      const char *url,
-      svn_revnum_t rev,
-      const char *prop_name,
-      const svn_string_t *prop_value,
-      const char *src_file,
-      svn_revnum_t head,
-      const char *anchor,
-      svn_ra_session_t *session,
-      struct operation *operation,
-      apr_pool_t *pool)
-{
-  apr_array_header_t *path_bits = svn_path_decompose(path, pool);
-  const char *path_so_far = "";
-  const char *copy_src = NULL;
-  svn_revnum_t copy_rev = SVN_INVALID_REVNUM;
-  int i;
-
-  /* Look for any previous operations we've recognized for PATH.  If
-     any of PATH's ancestors have not yet been traversed, we'll be
-     creating OP_OPEN operations for them as we walk down PATH's path
-     components. */
-  for (i = 0; i < path_bits->nelts; ++i)
-    {
-      const char *path_bit = APR_ARRAY_IDX(path_bits, i, const char *);
-      path_so_far = svn_relpath_join(path_so_far, path_bit, pool);
-      operation = get_operation(path_so_far, operation, pool);
-
-      /* If we cross a replace- or add-with-history, remember the
-      source of those things in case we need to lookup the node kind
-      of one of their children.  And if this isn't such a copy,
-      but we've already seen one in of our parent paths, we just need
-      to extend that copy source path by our current path
-      component. */
-      if (operation->url
-          && SVN_IS_VALID_REVNUM(operation->rev)
-          && (operation->operation == OP_REPLACE
-              || operation->operation == OP_ADD))
-        {
-          copy_src = subtract_anchor(anchor, operation->url, pool);
-          copy_rev = operation->rev;
-        }
-      else if (copy_src)
-        {
-          copy_src = svn_relpath_join(copy_src, path_bit, pool);
-        }
-    }
-
-  /* Handle property changes. */
-  if (prop_name)
-    {
-      if (operation->operation == OP_DELETE)
-        return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                                 "cannot set properties on a location being"
-                                 " deleted ('%s')", path);
-      /* If we're not adding this thing ourselves, check for existence.  */
-      if (! ((operation->operation == OP_ADD) ||
-             (operation->operation == OP_REPLACE)))
-        {
-          SVN_ERR(svn_ra_check_path(session,
-                                    copy_src ? copy_src : path,
-                                    copy_src ? copy_rev : head,
-                                    &operation->kind, pool));
-          if (operation->kind == svn_node_none)
-            return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                                     "propset: '%s' not found", path);
-          else if ((operation->kind == svn_node_file)
-                   && (operation->operation == OP_OPEN))
-            operation->operation = OP_PROPSET;
-        }
-      if (! prop_value)
-        APR_ARRAY_PUSH(operation->prop_dels, const char *) = prop_name;
-      else
-        svn_hash_sets(operation->prop_mods, prop_name, prop_value);
-      if (!operation->rev)
-        operation->rev = rev;
-      return SVN_NO_ERROR;
-    }
-
-  /* We won't fuss about multiple operations on the same path in the
-     following cases:
-
-       - the prior operation was, in fact, a no-op (open)
-       - the prior operation was a propset placeholder
-       - the prior operation was a deletion
-
-     Note: while the operation structure certainly supports the
-     ability to do a copy of a file followed by a put of new contents
-     for the file, we don't let that happen (yet).
-  */
-  if (operation->operation != OP_OPEN
-      && operation->operation != OP_PROPSET
-      && operation->operation != OP_DELETE)
-    return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                             "unsupported multiple operations on '%s'", path);
-
-  /* For deletions, we validate that there's actually something to
-     delete.  If this is a deletion of the child of a copied
-     directory, we need to remember to look in the copy source tree to
-     verify that this thing actually exists. */
-  if (action == ACTION_RM)
-    {
-      operation->operation = OP_DELETE;
-      SVN_ERR(svn_ra_check_path(session,
-                                copy_src ? copy_src : path,
-                                copy_src ? copy_rev : head,
-                                &operation->kind, pool));
-      if (operation->kind == svn_node_none)
-        {
-          if (copy_src && strcmp(path, copy_src))
-            return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                                     "'%s' (from '%s:%ld') not found",
-                                     path, copy_src, copy_rev);
-          else
-            return svn_error_createf(SVN_ERR_BAD_URL, NULL, "'%s' not found",
-                                     path);
-        }
-    }
-  /* Handle copy operations (which can be adds or replacements). */
-  else if (action == ACTION_CP)
-    {
-      if (rev > head)
-        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
-                                "Copy source revision cannot be younger "
-                                "than base revision");
-      operation->operation =
-        operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
-      if (operation->operation == OP_ADD)
-        {
-          /* There is a bug in the current version of mod_dav_svn
-             which incorrectly replaces existing directories.
-             Therefore we need to check if the target exists
-             and raise an error here. */
-          SVN_ERR(svn_ra_check_path(session,
-                                    copy_src ? copy_src : path,
-                                    copy_src ? copy_rev : head,
-                                    &operation->kind, pool));
-          if (operation->kind != svn_node_none)
-            {
-              if (copy_src && strcmp(path, copy_src))
-                return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                                         "'%s' (from '%s:%ld') already exists",
-                                         path, copy_src, copy_rev);
-              else
-                return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                                         "'%s' already exists", path);
-            }
-        }
-      SVN_ERR(svn_ra_check_path(session, subtract_anchor(anchor, url, pool),
-                                rev, &operation->kind, pool));
-      if (operation->kind == svn_node_none)
-        return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                                 "'%s' not found",
-                                  subtract_anchor(anchor, url, pool));
-      operation->url = url;
-      operation->rev = rev;
-    }
-  /* Handle mkdir operations (which can be adds or replacements). */
-  else if (action == ACTION_MKDIR)
-    {
-      operation->operation =
-        operation->operation == OP_DELETE ? OP_REPLACE : OP_ADD;
-      operation->kind = svn_node_dir;
-    }
-  /* Handle put operations (which can be adds, replacements, or opens). */
-  else if (action == ACTION_PUT)
-    {
-      if (operation->operation == OP_DELETE)
-        {
-          operation->operation = OP_REPLACE;
-        }
-      else
-        {
-          SVN_ERR(svn_ra_check_path(session,
-                                    copy_src ? copy_src : path,
-                                    copy_src ? copy_rev : head,
-                                    &operation->kind, pool));
-          if (operation->kind == svn_node_file)
-            operation->operation = OP_OPEN;
-          else if (operation->kind == svn_node_none)
-            operation->operation = OP_ADD;
-          else
-            return svn_error_createf(SVN_ERR_BAD_URL, NULL,
-                                     "'%s' is not a file", path);
-        }
-      operation->kind = svn_node_file;
-      operation->src_file = src_file;
-    }
-  else
-    {
-      /* We shouldn't get here. */
-      SVN_ERR_MALFUNCTION();
-    }
-
-  return SVN_NO_ERROR;
-}
 
 struct action {
   action_code_t action;
@@ -547,121 +134,84 @@ execute(const apr_array_header_t *action
         const char *anchor,
         apr_hash_t *revprops,
         svn_revnum_t base_revision,
-        svn_boolean_t non_interactive,
         svn_client_ctx_t *ctx,
         apr_pool_t *pool)
 {
-  svn_ra_session_t *session;
-  svn_revnum_t head;
-  const svn_delta_editor_t *editor;
-  void *editor_baton;
-  struct operation root;
+  svn_client_mtcc_t *mtcc;
+  apr_pool_t *iterpool = svn_pool_create(pool);
   svn_error_t *err;
   int i;
 
-  if (! svn_hash_gets(revprops, SVN_PROP_REVISION_LOG))
-    {
-      svn_string_t *msg = svn_string_create("", pool);
-
-      /* If we can do so, try to pop up $EDITOR to fetch a log message. */
-      if (non_interactive)
-        {
-          return svn_error_create
-            (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
-             _("Cannot invoke editor to get log message "
-               "when non-interactive"));
-        }
-      else
-        {
-          SVN_ERR(svn_cmdline__edit_string_externally(
-                      &msg, NULL, NULL, "", msg, "svnmucc-commit", ctx->config,
-                      TRUE, NULL, apr_hash_pool_get(revprops)));
-        }
-
-      svn_hash_sets(revprops, SVN_PROP_REVISION_LOG, msg);
-    }
-
-  SVN_ERR(svn_client_open_ra_session2(&session, anchor, NULL /* wri_abspath */,
-                                      ctx, pool, pool));
-  SVN_ERR(svn_ra_get_latest_revnum(session, &head, pool));
-  /* Reparent to ANCHOR's dir, if ANCHOR is not a directory. */
-  {
-    svn_node_kind_t kind;
-
-    SVN_ERR(svn_ra_check_path(session, "", head, &kind, pool));
-
-    if (kind != svn_node_dir)
-      {
-        anchor = svn_uri_dirname(anchor, pool);
-        SVN_ERR(svn_ra_reparent(session, anchor, pool));
-      }
-  }
-
-  if (SVN_IS_VALID_REVNUM(base_revision))
-    {
-      if (base_revision > head)
-        return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
-                                 "No such revision %ld (youngest is %ld)",
-                                 base_revision, head);
-      head = base_revision;
-    }
-
-  memset(&root, 0, sizeof(root));
-  root.children = apr_hash_make(pool);
-  root.operation = OP_OPEN;
-  root.kind = svn_node_dir; /* For setting properties */
-  root.prop_mods = apr_hash_make(pool);
-  root.prop_dels = apr_array_make(pool, 1, sizeof(const char *));
+  SVN_ERR(svn_client_mtcc_create(&mtcc, anchor,
+                                 SVN_IS_VALID_REVNUM(base_revision)
+                                    ? base_revision
+                                    : SVN_INVALID_REVNUM,
+                                 ctx, pool, iterpool));
 
   for (i = 0; i < actions->nelts; ++i)
     {
       struct action *action = APR_ARRAY_IDX(actions, i, struct action *);
       const char *path1, *path2;
+      svn_node_kind_t kind;
+
+      svn_pool_clear(iterpool);
+
       switch (action->action)
         {
         case ACTION_MV:
           path1 = subtract_anchor(anchor, action->path[0], pool);
           path2 = subtract_anchor(anchor, action->path[1], pool);
-          SVN_ERR(build(ACTION_RM, path1, NULL,
-                        SVN_INVALID_REVNUM, NULL, NULL, NULL, head, anchor,
-                        session, &root, pool));
-          SVN_ERR(build(ACTION_CP, path2, action->path[0],
-                        head, NULL, NULL, NULL, head, anchor,
-                        session, &root, pool));
+          SVN_ERR(svn_client_mtcc_add_move(path1, path2, mtcc, iterpool));
           break;
         case ACTION_CP:
+          path1 = subtract_anchor(anchor, action->path[0], pool);
           path2 = subtract_anchor(anchor, action->path[1], pool);
-          if (action->rev == SVN_INVALID_REVNUM)
-            action->rev = head;
-          SVN_ERR(build(ACTION_CP, path2, action->path[0],
-                        action->rev, NULL, NULL, NULL, head, anchor,
-                        session, &root, pool));
+          SVN_ERR(svn_client_mtcc_add_copy(path1, action->rev, path2,
+                                           mtcc, iterpool));
           break;
         case ACTION_RM:
           path1 = subtract_anchor(anchor, action->path[0], pool);
-          SVN_ERR(build(ACTION_RM, path1, NULL,
-                        SVN_INVALID_REVNUM, NULL, NULL, NULL, head, anchor,
-                        session, &root, pool));
+          SVN_ERR(svn_client_mtcc_add_delete(path1, mtcc, iterpool));
           break;
         case ACTION_MKDIR:
           path1 = subtract_anchor(anchor, action->path[0], pool);
-          SVN_ERR(build(ACTION_MKDIR, path1, action->path[0],
-                        SVN_INVALID_REVNUM, NULL, NULL, NULL, head, anchor,
-                        session, &root, pool));
+          SVN_ERR(svn_client_mtcc_add_mkdir(path1, mtcc, iterpool));
           break;
         case ACTION_PUT:
           path1 = subtract_anchor(anchor, action->path[0], pool);
-          SVN_ERR(build(ACTION_PUT, path1, action->path[0],
-                        SVN_INVALID_REVNUM, NULL, NULL, action->path[1],
-                        head, anchor, session, &root, pool));
+          SVN_ERR(svn_client_mtcc_check_path(&kind, path1, TRUE, mtcc, pool));
+
+          if (kind == svn_node_dir)
+            {
+              SVN_ERR(svn_client_mtcc_add_delete(path1, mtcc, pool));
+              kind = svn_node_none;
+            }
+
+          {
+            svn_stream_t *src;
+
+            if (strcmp(action->path[1], "-") != 0)
+              SVN_ERR(svn_stream_open_readonly(&src, action->path[1],
+                                               pool, iterpool));
+            else
+              SVN_ERR(svn_stream_for_stdin(&src, pool));
+
+
+            if (kind == svn_node_file)
+              SVN_ERR(svn_client_mtcc_add_update_file(path1, src, NULL,
+                                                      NULL, NULL,
+                                                      mtcc, iterpool));
+            else if (kind == svn_node_none)
+              SVN_ERR(svn_client_mtcc_add_add_file(path1, src, NULL,
+                                                   mtcc, iterpool));
+          }
           break;
         case ACTION_PROPSET:
         case ACTION_PROPDEL:
           path1 = subtract_anchor(anchor, action->path[0], pool);
-          SVN_ERR(build(action->action, path1, action->path[0],
-                        SVN_INVALID_REVNUM,
-                        action->prop_name, action->prop_value,
-                        NULL, head, anchor, session, &root, pool));
+          SVN_ERR(svn_client_mtcc_add_propset(path1, action->prop_name,
+                                              action->prop_value, FALSE,
+                                              mtcc, iterpool));
           break;
         case ACTION_PROPSETF:
         default:
@@ -669,23 +219,11 @@ execute(const apr_array_header_t *action
         }
     }
 
-  SVN_ERR(svn_ra_get_commit_editor3(session, &editor, &editor_baton, revprops,
-                                    commit_callback, NULL, NULL, FALSE, pool));
-
-  SVN_ERR(editor->open_root(editor_baton, head, pool, &root.baton));
-  err = change_props(editor, root.baton, &root, pool);
-  if (!err)
-    err = drive(&root, head, editor, pool);
-  if (!err)
-    err = editor->close_directory(root.baton, pool);
-  if (!err)
-    err = editor->close_edit(editor_baton, pool);
+  err = svn_client_mtcc_commit(revprops, commit_callback, NULL,
+                               mtcc, iterpool);
 
-  if (err)
-    err = svn_error_compose_create(err,
-                                   editor->abort_edit(editor_baton, pool));
-
-  return err;
+  svn_pool_destroy(iterpool);
+  return svn_error_trace(err);;
 }
 
 static svn_error_t *
@@ -798,42 +336,100 @@ mutually_exclusive_logs_error(void)
                             "exclusive"));
 }
 
-/* Ensure that the REVPROPS hash contains a command-line-provided log
-   message, if any, and that there was but one source of such a thing
-   provided on that command-line.  */
+/* Obtain the log message from multiple sources, producing an error
+   if there are multiple sources. Store the result in *FINAL_MESSAGE.  */
 static svn_error_t *
-sanitize_log_sources(apr_hash_t *revprops,
+sanitize_log_sources(const char **final_message,
                      const char *message,
-                     svn_stringbuf_t *filedata)
+                     apr_hash_t *revprops,
+                     svn_stringbuf_t *filedata,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
 {
-  apr_pool_t *hash_pool = apr_hash_pool_get(revprops);
+  svn_string_t *msg;
 
+  *final_message = NULL;
   /* If we already have a log message in the revprop hash, then just
      make sure the user didn't try to also use -m or -F.  Otherwise,
      we need to consult -m or -F to find a log message, if any. */
-  if (svn_hash_gets(revprops, SVN_PROP_REVISION_LOG))
+  msg = svn_hash_gets(revprops, SVN_PROP_REVISION_LOG);
+  if (msg)
     {
       if (filedata || message)
         return mutually_exclusive_logs_error();
+
+      *final_message = apr_pstrdup(result_pool, msg->data);
+
+      /* Will be re-added by libsvn_client */
+      svn_hash_sets(revprops, SVN_PROP_REVISION_LOG, NULL);
     }
   else if (filedata)
     {
       if (message)
         return mutually_exclusive_logs_error();
 
-      SVN_ERR(svn_utf_cstring_to_utf8(&message, filedata->data, hash_pool));
-      svn_hash_sets(revprops, SVN_PROP_REVISION_LOG,
-                    svn_stringbuf__morph_into_string(filedata));
+      SVN_ERR(svn_utf_cstring_to_utf8(&message, filedata->data,
+                                      scratch_pool));
+
+      *final_message = apr_pstrdup(result_pool, message);
     }
   else if (message)
     {
-      svn_hash_sets(revprops, SVN_PROP_REVISION_LOG,
-                    svn_string_create(message, hash_pool));
+      *final_message = apr_pstrdup(result_pool, message);
     }
 
   return SVN_NO_ERROR;
 }
 
+/* Baton for log_message_func */
+struct log_message_baton
+{
+  svn_boolean_t non_interactive;
+  const char *log_message;
+  svn_client_ctx_t *ctx;
+};
+
+/* Implements svn_client_get_commit_log3_t */
+static svn_error_t *
+log_message_func(const char **log_msg,
+                 const char **tmp_file,
+                 const apr_array_header_t *commit_items,
+                 void *baton,
+                 apr_pool_t *pool)
+{
+  struct log_message_baton *lmb = baton;
+
+  *tmp_file = NULL;
+
+  if (lmb->log_message)
+    {
+      *log_msg = apr_pstrdup(pool, lmb->log_message);
+      return SVN_NO_ERROR;
+    }
+
+  if (lmb->non_interactive)
+    {
+      return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
+                              _("Cannot invoke editor to get log message "
+                                "when non-interactive"));
+    }
+  else
+    {
+      svn_string_t *msg = svn_string_create("", pool);
+
+      SVN_ERR(svn_cmdline__edit_string_externally(
+                      &msg, NULL, NULL, "", msg, "svnmucc-commit",
+                      lmb->ctx->config, TRUE, NULL, pool));
+
+      if (msg && msg->data)
+        *log_msg = msg->data;
+      else
+        *log_msg = NULL;
+
+      return SVN_NO_ERROR;
+    }
+}
+
 /*
  * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
  * either return an error to be displayed, or set *EXIT_CODE to non-zero and
@@ -893,6 +489,7 @@ sub_main(int *exit_code, int argc, const
   apr_hash_t *cfg_hash;
   svn_config_t *cfg_config;
   svn_client_ctx_t *ctx;
+  struct log_message_baton lmb;
   int i;
 
   /* Check library versions */
@@ -1007,9 +604,6 @@ sub_main(int *exit_code, int argc, const
                                 "--non-interactive"));
     }
 
-  /* Make sure we have a log message to use. */
-  SVN_ERR(sanitize_log_sources(revprops, message, filedata));
-
   /* Copy the rest of our command-line arguments to an array,
      UTF-8-ing them along the way. */
   action_args = apr_array_make(pool, opts->argc, sizeof(const char *));
@@ -1076,6 +670,15 @@ sub_main(int *exit_code, int argc, const
                                         ctx->cancel_baton,
                                         pool));
 
+  lmb.non_interactive = non_interactive;
+  lmb.ctx = ctx;
+    /* Make sure we have a log message to use. */
+  SVN_ERR(sanitize_log_sources(&lmb.log_message, message, revprops, filedata,
+                               pool, pool));
+
+  ctx->log_msg_func3 = log_message_func;
+  ctx->log_msg_baton3 = &lmb;
+
   /* Now, we iterate over the combined set of arguments -- our actions. */
   for (i = 0; i < action_args->nelts; )
     {
@@ -1268,8 +871,7 @@ sub_main(int *exit_code, int argc, const
       return SVN_NO_ERROR;
     }
 
-  if ((err = execute(actions, anchor, revprops, base_revision,
-                     non_interactive, ctx, pool)))
+  if ((err = execute(actions, anchor, revprops, base_revision, ctx, pool)))
     {
       if (err->apr_err == SVN_ERR_AUTHN_FAILED && non_interactive)
         err = svn_error_quick_wrap(err,

Modified: subversion/trunk/subversion/tests/cmdline/svnmucc_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svnmucc_tests.py?rev=1550968&r1=1550967&r2=1550968&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svnmucc_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svnmucc_tests.py Sat Dec 14 20:45:12 2013
@@ -310,22 +310,21 @@ def basic_svnmucc(sbox):
 
   # Expected cannot be younger error
   xtest_svnmucc(sbox.repo_url,
-                ['svnmucc: E205000: Copy source revision cannot be younger ' +
-                 'than base revision',
+                ['svnmucc: E160006: No such revision 42',
                  ], #---------
                 '-m', 'log msg',
                 'cp', '42', 'a', 'b')
 
   # Expected already exists error
   xtest_svnmucc(sbox.repo_url,
-                ["svnmucc: E125002: 'foo' already exists",
+                ["svnmucc: E160020: Path 'foo' already exists",
                  ], #---------
                 '-m', 'log msg',
                 'cp', '17', 'a', 'foo')
 
   # Expected copy_src already exists error
   xtest_svnmucc(sbox.repo_url,
-                ["svnmucc: E125002: 'a/bar' (from 'foo/bar:17') already exists",
+                ["svnmucc: E160020: Path 'a/bar' already exists",
                  ], #---------
                 '-m', 'log msg',
                 'cp', '17', 'foo', 'a',
@@ -333,7 +332,7 @@ def basic_svnmucc(sbox):
 
   # Expected not found error
   xtest_svnmucc(sbox.repo_url,
-                ["svnmucc: E125002: 'a' not found",
+                ["svnmucc: E160013: Path 'a' not found in revision 17",
                  ], #---------
                 '-m', 'log msg',
                 'cp', '17', 'a', 'b')



Mime
View raw message