Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h	(revision 12493)
+++ subversion/include/svn_client.h	(working copy)
@@ -602,11 +602,25 @@
  * this function can use to query for a commit log message when one is
  * needed.
  *
+ * If @a make_parents is true, behaves like mkdir -p and creates parent
+ * directories if needed.
+ *
  * If @a ctx->notify_func is non-null, when the directory has been created
  * (successfully) in the working copy, call @a ctx->notify_func with
  * @a ctx->notify_baton and the path of the new directory.  Note that this is
  * only called for items added to the working copy.  */
 svn_error_t *
+svn_client_mkdir2 (svn_client_commit_info_t **commit_info,
+                   const apr_array_header_t *paths,
+                   svn_boolean_t make_parents,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool);
+
+
+/** Create a directory, either in a repository or in a working copy.
+ *
+ * Just like svn_client_mkdir2, but never creates parent directories. */
+svn_error_t *
 svn_client_mkdir (svn_client_commit_info_t **commit_info,
                   const apr_array_header_t *paths,
                   svn_client_ctx_t *ctx,
Index: subversion/libsvn_client/add.c
===================================================================
--- subversion/libsvn_client/add.c	(revision 12493)
+++ subversion/libsvn_client/add.c	(working copy)
@@ -607,6 +607,66 @@
                   svn_client_ctx_t *ctx,
                   apr_pool_t *pool)
 {
+  return svn_client_mkdir2(commit_info, paths, FALSE, ctx, pool);
+}
+
+/** Make a directory and add it to the repository.
+  * If the parent directory doesn't exist, create it.
+  */
+
+static svn_error_t *
+svn_client__mksubdir (const char *path,
+                      svn_boolean_t make_parents,
+                      svn_client_ctx_t *ctx,
+                      apr_pool_t *pool)
+{
+  svn_error_t *err;
+  
+  /* if we're making parents as needed, we have to check for existence first */
+  if (make_parents)
+    {
+      const char *path_parent, *path_name;
+      svn_node_kind_t node_kind;
+
+      svn_path_split(path, &path_parent, &path_name, pool);
+
+      /* find out if the file exists */
+      SVN_ERR(svn_io_check_path(path_parent, &node_kind, pool));
+
+      if (node_kind == svn_node_none)
+        {
+          /* recurse to create parent */
+          SVN_ERR(svn_client__mksubdir(path_parent, TRUE,
+                                       ctx, pool));
+        }
+    }
+
+
+  SVN_ERR(svn_io_dir_make (path, APR_OS_DEFAULT, pool));
+  
+  err = svn_client_add(path, FALSE, ctx, pool);
+  
+  /* We just created a new directory, but couldn't add it to
+     version control. Don't leave unversioned directoies behind. */
+  if (err)
+    {
+      /* ### If this returns an error, should we link it onto
+         err instead, so that the user is warned that we just
+         created an unversioned directory? */
+
+      svn_error_clear (svn_io_remove_dir (path, pool));
+    }
+
+  return err;
+}
+
+svn_error_t *
+svn_client_mkdir2 (svn_client_commit_info_t **commit_info,
+                   const apr_array_header_t *paths,
+                   svn_boolean_t make_parents,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool)
+{
   if (! paths->nelts)
     return SVN_NO_ERROR;
   
@@ -629,20 +689,9 @@
           if (ctx->cancel_func)
             SVN_ERR (ctx->cancel_func (ctx->cancel_baton));
 
-          SVN_ERR (svn_io_dir_make (path, APR_OS_DEFAULT, pool));
-          err = svn_client_add (path, FALSE, ctx, pool);
+          SVN_ERR (svn_client__mksubdir (path, make_parents, 
+                                         ctx, subpool));
 
-          /* We just created a new directory, but couldn't add it to
-             version control. Don't leave unversioned directoies behind. */
-          if (err)
-            {
-              /* ### If this returns an error, should we link it onto
-                 err instead, so that the user is warned that we just
-                 created an unversioned directory? */
-              svn_error_clear (svn_io_remove_dir (path, pool));
-              return err;
-            }
-
           svn_pool_clear (subpool);
         }
       svn_pool_destroy (subpool);
Index: subversion/clients/cmdline/cl.h
===================================================================
--- subversion/clients/cmdline/cl.h	(revision 12493)
+++ subversion/clients/cmdline/cl.h	(working copy)
@@ -135,6 +135,7 @@
   svn_boolean_t autoprops;       /* enable automatic properties */
   svn_boolean_t no_autoprops;    /* disable automatic properties */
   const char *native_eol;        /* override system standard eol marker */
+  svn_boolean_t parents;         /* create parent directories (mkdir) */
 } svn_cl__opt_state_t;
 
 
Index: subversion/clients/cmdline/mkdir-cmd.c
===================================================================
--- subversion/clients/cmdline/mkdir-cmd.c	(revision 12493)
+++ subversion/clients/cmdline/mkdir-cmd.c	(working copy)
@@ -58,7 +58,8 @@
   SVN_ERR (svn_cl__make_log_msg_baton (&(ctx->log_msg_baton), opt_state,
                                        NULL, ctx->config, subpool));
   err = svn_cl__cleanup_log_msg
-    (ctx->log_msg_baton, svn_client_mkdir (&commit_info, targets, 
+    (ctx->log_msg_baton, svn_client_mkdir2 (&commit_info, targets, 
+                                           opt_state->parents,
                                            ctx, subpool));
   if (err)
     {
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c	(revision 12493)
+++ subversion/clients/cmdline/main.c	(working copy)
@@ -144,6 +144,8 @@
                       "of 'LF', 'CR', 'CRLF'")},
     {"limit",         svn_cl__limit_opt, 1,
                       N_("maximum number of log entries")},
+    {"parents",       'p', 0, N_("make parent directories as needed\n"
+                      "                             (WC only)")},
     {0,               0, 0, 0}
   };
 
@@ -448,9 +450,12 @@
        "via\n"
        "    an immediate commit.\n"
        "\n"
-       "  In both cases, all the intermediate directories must already "
+       "  In case 1, intermediate directories are created as needed if\n"
+       "    -p is specified.\n"
+       "\n"
+       "  Otherwise, all the intermediate directories must already "
        "exist.\n"),
-    {'q',
+    {'q', 'p',
      SVN_CL__LOG_MSG_OPTIONS, SVN_CL__AUTH_OPTIONS, svn_cl__config_dir_opt} },
 
   { "move", svn_cl__move, {"mv", "rename", "ren"},
@@ -919,6 +924,9 @@
       case svn_cl__revprop_opt:
         opt_state.revprop = TRUE;
         break;
+      case 'p':
+        opt_state.parents = TRUE;
+        break;
       case 'R':
         opt_state.recursive = TRUE;
         break;
Index: subversion/tests/clients/cmdline/basic_tests.py
===================================================================
--- subversion/tests/clients/cmdline/basic_tests.py	(revision 12493)
+++ subversion/tests/clients/cmdline/basic_tests.py	(working copy)
@@ -252,6 +252,60 @@
                                         expected_status)
 
 #----------------------------------------------------------------------
+def basic_mkdir_missing_parent(sbox):
+  "basic mkdir missingparent/path (should fail)"
+
+  sbox.build()
+
+  Y_Z_path = os.path.join(sbox.wc_dir, 'Y', 'Z')
+
+  svntest.actions.run_and_verify_svn("mkdir dir dir/subdir", [],
+                                     SVNAnyOutput,
+                                     'mkdir', Y_Z_path)
+
+#----------------------------------------------------------------------
+def basic_mkdir_missing_parent_p(sbox):
+  "basic mkdir -p missingparent/path"
+
+  sbox.build()
+
+  Y_Z_path = os.path.join(sbox.wc_dir, 'Y', 'Z')
+
+  svntest.actions.run_and_verify_svn("mkdir dir dir/subdir", None, [],
+                                     'mkdir', '-p', Y_Z_path)
+
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+  expected_status.add({
+    'Y'   : Item(status='A ', wc_rev=0, repos_rev=1),
+    'Y/Z' : Item(status='A ', wc_rev=0, repos_rev=1)
+    })
+
+  svntest.actions.run_and_verify_status(sbox.wc_dir,
+                                        expected_status)
+
+
+#----------------------------------------------------------------------
+def basic_mkdir_wcpath(sbox):
+  "basic mkdir wcpath"
+
+  sbox.build()
+
+  Y_path = os.path.join(sbox.wc_dir, 'Y')
+  Y_Z_path = os.path.join(sbox.wc_dir, 'Y', 'Z')
+
+  svntest.actions.run_and_verify_svn("mkdir dir dir/subdir", None, [],
+                                     'mkdir', Y_path, Y_Z_path)
+
+  expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1)
+  expected_status.add({
+    'Y'   : Item(status='A ', wc_rev=0, repos_rev=1),
+    'Y/Z' : Item(status='A ', wc_rev=0, repos_rev=1)
+    })
+
+  svntest.actions.run_and_verify_status(sbox.wc_dir,
+                                        expected_status)
+
+#----------------------------------------------------------------------
 def basic_corruption(sbox):
   "basic corruption detection"
 
@@ -1708,6 +1762,9 @@
               basic_commit,
               basic_update,
               basic_mkdir_url,
+              basic_mkdir_wcpath,
+              basic_mkdir_missing_parent,
+              basic_mkdir_missing_parent_p,
               basic_corruption,
               basic_merging_update,
               basic_conflict,


