You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/02/04 21:48:13 UTC

svn commit: r1442344 [5/39] - in /subversion/branches/fsfs-format7: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/client-side/emacs/ contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ doc/ ...

Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/commit.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/commit.c Mon Feb  4 20:48:05 2013
@@ -30,11 +30,8 @@
 #include <string.h>
 #include <apr_strings.h>
 #include <apr_hash.h>
-#include <apr_md5.h>
 #include "svn_wc.h"
 #include "svn_ra.h"
-#include "svn_delta.h"
-#include "svn_subst.h"
 #include "svn_client.h"
 #include "svn_string.h"
 #include "svn_pools.h"
@@ -42,743 +39,14 @@
 #include "svn_error_codes.h"
 #include "svn_dirent_uri.h"
 #include "svn_path.h"
-#include "svn_io.h"
-#include "svn_time.h"
 #include "svn_sorts.h"
-#include "svn_props.h"
 
 #include "client.h"
 #include "private/svn_wc_private.h"
-#include "private/svn_subr_private.h"
 #include "private/svn_ra_private.h"
-#include "private/svn_magic.h"
 
 #include "svn_private_config.h"
 
-/* Import context baton.
-
-   ### TODO:  Add the following items to this baton:
-      /` import editor/baton. `/
-      const svn_delta_editor_t *editor;
-      void *edit_baton;
-
-      /` Client context baton `/
-      svn_client_ctx_t `ctx;
-
-      /` Paths (keys) excluded from the import (values ignored) `/
-      apr_hash_t *excludes;
-*/
-typedef struct import_ctx_t
-{
-  /* Whether any changes were made to the repository */
-  svn_boolean_t repos_changed;
-
-  /* A magic cookie for mime-type detection. */
-  svn_magic__cookie_t *magic_cookie;
-
-  /* Collection of all possible configuration file dictated auto-props and
-     svn:auto-props.  A hash mapping const char * file patterns to a
-     second hash which maps const char * property names to const char *
-     property values.  Properties which don't have a value, e.g.
-     svn:executable, simply map the property name to an empty string.
-     May be NULL if autoprops are disabled. */
-  apr_hash_t *autoprops;
-} import_ctx_t;
-
-
-/* Apply LOCAL_ABSPATH's contents (as a delta against the empty string) to
-   FILE_BATON in EDITOR.  Use POOL for any temporary allocation.
-   PROPERTIES is the set of node properties set on this file.
-
-   Fill DIGEST with the md5 checksum of the sent file; DIGEST must be
-   at least APR_MD5_DIGESTSIZE bytes long. */
-
-/* ### how does this compare against svn_wc_transmit_text_deltas2() ??? */
-
-static svn_error_t *
-send_file_contents(const char *local_abspath,
-                   void *file_baton,
-                   const svn_delta_editor_t *editor,
-                   apr_hash_t *properties,
-                   unsigned char *digest,
-                   apr_pool_t *pool)
-{
-  svn_stream_t *contents;
-  svn_txdelta_window_handler_t handler;
-  void *handler_baton;
-  const svn_string_t *eol_style_val = NULL, *keywords_val = NULL;
-  svn_boolean_t special = FALSE;
-  svn_subst_eol_style_t eol_style;
-  const char *eol;
-  apr_hash_t *keywords;
-
-  /* If there are properties, look for EOL-style and keywords ones. */
-  if (properties)
-    {
-      eol_style_val = apr_hash_get(properties, SVN_PROP_EOL_STYLE,
-                                   sizeof(SVN_PROP_EOL_STYLE) - 1);
-      keywords_val = apr_hash_get(properties, SVN_PROP_KEYWORDS,
-                                  sizeof(SVN_PROP_KEYWORDS) - 1);
-      if (apr_hash_get(properties, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING))
-        special = TRUE;
-    }
-
-  /* Get an editor func that wants to consume the delta stream. */
-  SVN_ERR(editor->apply_textdelta(file_baton, NULL, pool,
-                                  &handler, &handler_baton));
-
-  if (eol_style_val)
-    svn_subst_eol_style_from_value(&eol_style, &eol, eol_style_val->data);
-  else
-    {
-      eol = NULL;
-      eol_style = svn_subst_eol_style_none;
-    }
-
-  if (keywords_val)
-    SVN_ERR(svn_subst_build_keywords2(&keywords, keywords_val->data,
-                                      APR_STRINGIFY(SVN_INVALID_REVNUM),
-                                      "", 0, "", pool));
-  else
-    keywords = NULL;
-
-  if (special)
-    {
-      SVN_ERR(svn_subst_read_specialfile(&contents, local_abspath,
-                                         pool, pool));
-    }
-  else
-    {
-      /* Open the working copy file. */
-      SVN_ERR(svn_stream_open_readonly(&contents, local_abspath, pool, pool));
-
-      /* If we have EOL styles or keywords, then detranslate the file. */
-      if (svn_subst_translation_required(eol_style, eol, keywords,
-                                         FALSE, TRUE))
-        {
-          if (eol_style == svn_subst_eol_style_unknown)
-            return svn_error_createf(SVN_ERR_IO_UNKNOWN_EOL, NULL,
-                                    _("%s property on '%s' contains "
-                                      "unrecognized EOL-style '%s'"),
-                                    SVN_PROP_EOL_STYLE,
-                                    svn_dirent_local_style(local_abspath,
-                                                           pool),
-                                    eol_style_val->data);
-
-          /* We're importing, so translate files with 'native' eol-style to
-           * repository-normal form, not to this platform's native EOL. */
-          if (eol_style == svn_subst_eol_style_native)
-            eol = SVN_SUBST_NATIVE_EOL_STR;
-
-          /* Wrap the working copy stream with a filter to detranslate it. */
-          contents = svn_subst_stream_translated(contents,
-                                                 eol,
-                                                 TRUE /* repair */,
-                                                 keywords,
-                                                 FALSE /* expand */,
-                                                 pool);
-        }
-    }
-
-  /* Send the file's contents to the delta-window handler. */
-  return svn_error_trace(svn_txdelta_send_stream(contents, handler,
-                                                 handler_baton, digest,
-                                                 pool));
-}
-
-
-/* Import file PATH as EDIT_PATH in the repository directory indicated
- * by DIR_BATON in EDITOR.
- *
- * Accumulate file paths and their batons in FILES, which must be
- * non-null.  (These are used to send postfix textdeltas later).
- *
- * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON
- * for each file.
- *
- * Use POOL for any temporary allocation.
- */
-static svn_error_t *
-import_file(const svn_delta_editor_t *editor,
-            void *dir_baton,
-            const char *local_abspath,
-            const char *edit_path,
-            const svn_io_dirent2_t *dirent,
-            import_ctx_t *import_ctx,
-            svn_client_ctx_t *ctx,
-            apr_pool_t *pool)
-{
-  void *file_baton;
-  const char *mimetype = NULL;
-  unsigned char digest[APR_MD5_DIGESTSIZE];
-  const char *text_checksum;
-  apr_hash_t* properties;
-  apr_hash_index_t *hi;
-
-  SVN_ERR(svn_path_check_valid(local_abspath, pool));
-
-  /* Add the file, using the pool from the FILES hash. */
-  SVN_ERR(editor->add_file(edit_path, dir_baton, NULL, SVN_INVALID_REVNUM,
-                           pool, &file_baton));
-
-  /* Remember that the repository was modified */
-  import_ctx->repos_changed = TRUE;
-
-  if (! dirent->special)
-    {
-      /* add automatic properties */
-      SVN_ERR(svn_client__get_paths_auto_props(&properties, &mimetype,
-                                               local_abspath,
-                                               import_ctx->magic_cookie,
-                                               import_ctx->autoprops,
-                                               ctx, pool, pool));
-    }
-  else
-    properties = apr_hash_make(pool);
-
-  if (properties)
-    {
-      for (hi = apr_hash_first(pool, properties); hi; hi = apr_hash_next(hi))
-        {
-          const char *pname = svn__apr_hash_index_key(hi);
-          const svn_string_t *pval = svn__apr_hash_index_val(hi);
-
-          SVN_ERR(editor->change_file_prop(file_baton, pname, pval, pool));
-        }
-    }
-
-  if (ctx->notify_func2)
-    {
-      svn_wc_notify_t *notify
-        = svn_wc_create_notify(local_abspath, svn_wc_notify_commit_added,
-                               pool);
-      notify->kind = svn_node_file;
-      notify->mime_type = mimetype;
-      notify->content_state = notify->prop_state
-        = svn_wc_notify_state_inapplicable;
-      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-      (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
-    }
-
-  /* If this is a special file, we need to set the svn:special
-     property and create a temporary detranslated version in order to
-     send to the server. */
-  if (dirent->special)
-    {
-      apr_hash_set(properties, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING,
-                   svn_string_create(SVN_PROP_BOOLEAN_TRUE, pool));
-      SVN_ERR(editor->change_file_prop(file_baton, SVN_PROP_SPECIAL,
-                                       apr_hash_get(properties,
-                                                    SVN_PROP_SPECIAL,
-                                                    APR_HASH_KEY_STRING),
-                                       pool));
-    }
-
-  /* Now, transmit the file contents. */
-  SVN_ERR(send_file_contents(local_abspath, file_baton, editor,
-                             properties, digest, pool));
-
-  /* Finally, close the file. */
-  text_checksum =
-    svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool);
-
-  return editor->close_file(file_baton, text_checksum, pool);
-}
-
-
-/* Return in CHILDREN a mapping of basenames to dirents for the importable
- * children of DIR_ABSPATH.  EXCLUDES is a hash of absolute paths to filter
- * out.  IGNORES and GLOBAL_IGNORES, if non-NULL, are lists of basename
- * patterns to filter out.
- * FILTER_CALLBACK and FILTER_BATON will be called for each absolute path,
- * allowing users to further filter the list of returned entries.
- *
- * Results are returned in RESULT_POOL; use SCRATCH_POOL for temporary data.*/
-static svn_error_t *
-get_filtered_children(apr_hash_t **children,
-                      const char *dir_abspath,
-                      apr_hash_t *excludes,
-                      apr_array_header_t *ignores,
-                      apr_array_header_t *global_ignores,
-                      svn_client_import_filter_func_t filter_callback,
-                      void *filter_baton,
-                      svn_client_ctx_t *ctx,
-                      apr_pool_t *result_pool,
-                      apr_pool_t *scratch_pool)
-{
-  apr_hash_t *dirents;
-  apr_hash_index_t *hi;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-
-  SVN_ERR(svn_io_get_dirents3(&dirents, dir_abspath, TRUE, result_pool,
-                              scratch_pool));
-
-  for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
-    {
-      const char *base_name = svn__apr_hash_index_key(hi);
-      const svn_io_dirent2_t *dirent = svn__apr_hash_index_val(hi);
-      const char *local_abspath;
-
-      svn_pool_clear(iterpool);
-
-      local_abspath = svn_dirent_join(dir_abspath, base_name, iterpool);
-
-      if (svn_wc_is_adm_dir(base_name, iterpool))
-        {
-          /* If someone's trying to import a directory named the same
-             as our administrative directories, that's probably not
-             what they wanted to do.  If they are importing a file
-             with that name, something is bound to blow up when they
-             checkout what they've imported.  So, just skip items with
-             that name.  */
-          if (ctx->notify_func2)
-            {
-              svn_wc_notify_t *notify
-                = svn_wc_create_notify(svn_dirent_join(local_abspath, base_name,
-                                                       iterpool),
-                                       svn_wc_notify_skip, iterpool);
-              notify->kind = svn_node_dir;
-              notify->content_state = notify->prop_state
-                = svn_wc_notify_state_inapplicable;
-              notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-              (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
-            }
-
-          apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
-          continue;
-        }
-            /* If this is an excluded path, exclude it. */
-      if (apr_hash_get(excludes, local_abspath, APR_HASH_KEY_STRING))
-        {
-          apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
-          continue;
-        }
-
-      if (ignores && svn_wc_match_ignore_list(base_name, ignores, iterpool))
-        {
-          apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
-          continue;
-        }
-
-      if (global_ignores &&
-          svn_wc_match_ignore_list(base_name, global_ignores, iterpool))
-        {
-          apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
-          continue;
-        }
-
-      if (filter_callback)
-        {
-          svn_boolean_t filter = FALSE;
-
-          SVN_ERR(filter_callback(filter_baton, &filter, local_abspath,
-                                  dirent, iterpool));
-
-          if (filter)
-            {
-              apr_hash_set(dirents, base_name, APR_HASH_KEY_STRING, NULL);
-              continue;
-            }
-        }
-    }
-  svn_pool_destroy(iterpool);
-
-  *children = dirents;
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-import_dir(const svn_delta_editor_t *editor,
-           void *dir_baton,
-           const char *local_abspath,
-           const char *edit_path,
-           svn_depth_t depth,
-           apr_hash_t *excludes,
-           apr_array_header_t *global_ignores,
-           svn_boolean_t no_ignore,
-           svn_boolean_t no_autoprops,
-           svn_boolean_t ignore_unknown_node_types,
-           svn_client_import_filter_func_t filter_callback,
-           void *filter_baton,
-           import_ctx_t *import_ctx,
-           svn_client_ctx_t *ctx,
-           apr_pool_t *pool);
-
-
-/* Import the children of DIR_ABSPATH, with other arguments similar to
- * import_dir(). */
-static svn_error_t *
-import_children(const char *dir_abspath,
-                const char *edit_path,
-                apr_hash_t *dirents,
-                const svn_delta_editor_t *editor,
-                void *dir_baton,
-                svn_depth_t depth,
-                apr_hash_t *excludes,
-                apr_array_header_t *global_ignores,
-                svn_boolean_t no_ignore,
-                svn_boolean_t no_autoprops,
-                svn_boolean_t ignore_unknown_node_types,
-                svn_client_import_filter_func_t filter_callback,
-                void *filter_baton,
-                import_ctx_t *import_ctx,
-                svn_client_ctx_t *ctx,
-                apr_pool_t *scratch_pool)
-{
-  apr_array_header_t *sorted_dirents;
-  int i;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-
-  sorted_dirents = svn_sort__hash(dirents, svn_sort_compare_items_lexically,
-                                  scratch_pool);
-  for (i = 0; i < sorted_dirents->nelts; i++)
-    {
-      const char *this_abspath, *this_edit_path;
-      svn_sort__item_t item = APR_ARRAY_IDX(sorted_dirents, i,
-                                            svn_sort__item_t);
-      const char *filename = item.key;
-      const svn_io_dirent2_t *dirent = item.value;
-
-      svn_pool_clear(iterpool);
-
-      if (ctx->cancel_func)
-        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
-
-      /* Typically, we started importing from ".", in which case
-         edit_path is "".  So below, this_path might become "./blah",
-         and this_edit_path might become "blah", for example. */
-      this_abspath = svn_dirent_join(dir_abspath, filename, iterpool);
-      this_edit_path = svn_relpath_join(edit_path, filename, iterpool);
-
-      if (dirent->kind == svn_node_dir && depth >= svn_depth_immediates)
-        {
-          /* Recurse. */
-          svn_depth_t depth_below_here = depth;
-          if (depth == svn_depth_immediates)
-            depth_below_here = svn_depth_empty;
-
-          SVN_ERR(import_dir(editor, dir_baton, this_abspath,
-                             this_edit_path, depth_below_here, excludes,
-                             global_ignores, no_ignore, no_autoprops,
-                             ignore_unknown_node_types, filter_callback,
-                             filter_baton, import_ctx, ctx, iterpool));
-        }
-      else if (dirent->kind == svn_node_file && depth >= svn_depth_files)
-        {
-          SVN_ERR(import_file(editor, dir_baton, this_abspath,
-                              this_edit_path, dirent,
-                              import_ctx, ctx, iterpool));
-        }
-      else if (dirent->kind != svn_node_dir && dirent->kind != svn_node_file)
-        {
-          if (ignore_unknown_node_types)
-            {
-              /*## warn about it*/
-              if (ctx->notify_func2)
-                {
-                  svn_wc_notify_t *notify
-                    = svn_wc_create_notify(this_abspath,
-                                           svn_wc_notify_skip, iterpool);
-                  notify->kind = svn_node_dir;
-                  notify->content_state = notify->prop_state
-                    = svn_wc_notify_state_inapplicable;
-                  notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-                  (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
-                }
-            }
-          else
-            return svn_error_createf
-              (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-               _("Unknown or unversionable type for '%s'"),
-               svn_dirent_local_style(this_abspath, iterpool));
-        }
-    }
-
-  svn_pool_destroy(iterpool);
-  return SVN_NO_ERROR;
-}
-
-
-/* Import directory LOCAL_ABSPATH into the repository directory indicated by
- * DIR_BATON in EDITOR.  EDIT_PATH is the path imported as the root
- * directory, so all edits are relative to that.
- *
- * DEPTH is the depth at this point in the descent (it may be changed
- * for recursive calls).
- *
- * Accumulate file paths and their batons in FILES, which must be
- * non-null.  (These are used to send postfix textdeltas later).
- *
- * EXCLUDES is a hash whose keys are absolute paths to exclude from
- * the import (values are unused).
- *
- * GLOBAL_IGNORES is an array of const char * ignore patterns.  Any child
- * of LOCAL_ABSPATH which matches one or more of the patterns is not imported.
- *
- * If NO_IGNORE is FALSE, don't import files or directories that match
- * ignore patterns.
- *
- * If FILTER_CALLBACK is not NULL, call it with FILTER_BATON on each to be
- * imported node below LOCAL_ABSPATH to allow filtering nodes.
- *
- * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for each
- * directory.
- *
- * Use POOL for any temporary allocation.  */
-static svn_error_t *
-import_dir(const svn_delta_editor_t *editor,
-           void *dir_baton,
-           const char *local_abspath,
-           const char *edit_path,
-           svn_depth_t depth,
-           apr_hash_t *excludes,
-           apr_array_header_t *global_ignores,
-           svn_boolean_t no_ignore,
-           svn_boolean_t no_autoprops,
-           svn_boolean_t ignore_unknown_node_types,
-           svn_client_import_filter_func_t filter_callback,
-           void *filter_baton,
-           import_ctx_t *import_ctx,
-           svn_client_ctx_t *ctx,
-           apr_pool_t *pool)
-{
-  apr_hash_t *dirents;
-  void *this_dir_baton;
-
-  SVN_ERR(svn_path_check_valid(local_abspath, pool));
-  SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes, NULL,
-                                global_ignores, filter_callback,
-                                filter_baton, ctx, pool, pool));
-
-  /* Import this directory, but not yet its children. */
-  {
-    /* Add the new subdirectory, getting a descent baton from the editor. */
-    SVN_ERR(editor->add_directory(edit_path, dir_baton, NULL,
-                                  SVN_INVALID_REVNUM, pool, &this_dir_baton));
-
-    /* Remember that the repository was modified */
-    import_ctx->repos_changed = TRUE;
-
-    /* By notifying before the recursive call below, we display
-       a directory add before displaying adds underneath the
-       directory.  To do it the other way around, just move this
-       after the recursive call. */
-    if (ctx->notify_func2)
-      {
-        svn_wc_notify_t *notify
-          = svn_wc_create_notify(local_abspath, svn_wc_notify_commit_added,
-                                 pool);
-        notify->kind = svn_node_dir;
-        notify->content_state = notify->prop_state
-          = svn_wc_notify_state_inapplicable;
-        notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-        (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
-      }
-  }
-
-  /* Now import the children recursively. */
-  SVN_ERR(import_children(local_abspath, edit_path, dirents, editor,
-                          this_dir_baton, depth, excludes, global_ignores,
-                          no_ignore, no_autoprops, ignore_unknown_node_types,
-                          filter_callback, filter_baton,
-                          import_ctx, ctx, pool));
-
-  /* Finally, close the sub-directory. */
-  SVN_ERR(editor->close_directory(this_dir_baton, pool));
-
-  return SVN_NO_ERROR;
-}
-
-
-/* Recursively import PATH to a repository using EDITOR and
- * EDIT_BATON.  PATH can be a file or directory.
- *
- * DEPTH is the depth at which to import PATH; it behaves as for
- * svn_client_import4().
- *
- * NEW_ENTRIES is an ordered array of path components that must be
- * created in the repository (where the ordering direction is
- * parent-to-child).  If PATH is a directory, NEW_ENTRIES may be empty
- * -- the result is an import which creates as many new entries in the
- * top repository target directory as there are importable entries in
- * the top of PATH; but if NEW_ENTRIES is not empty, its last item is
- * the name of a new subdirectory in the repository to hold the
- * import.  If PATH is a file, NEW_ENTRIES may not be empty, and its
- * last item is the name used for the file in the repository.  If
- * NEW_ENTRIES contains more than one item, all but the last item are
- * the names of intermediate directories that are created before the
- * real import begins.  NEW_ENTRIES may NOT be NULL.
- *
- * EXCLUDES is a hash whose keys are absolute paths to exclude from
- * the import (values are unused).
- *
- * AUTOPROPS is hash of all config file autoprops and
- * svn:auto-props inherited by the import target, see the
- * IMPORT_CTX member of the same name.
- *
- * LOCAL_IGNORES is an array of const char * ignore patterns which
- * correspond to the svn:ignore property (if any) set on the root of the
- * repository target and thus dictates which immediate children of that
- * target should be ignored and not imported.
- *
- * GLOBAL_IGNORES is an array of const char * ignore patterns which
- * correspond to the svn:global-ignores properties (if any) set on
- * the root of the repository target or inherited by it.
- *
- * If NO_IGNORE is FALSE, don't import files or directories that match
- * ignore patterns.
- *
- * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for
- * each imported path, passing actions svn_wc_notify_commit_added.
- *
- * Use POOL for any temporary allocation.
- *
- * Note: the repository directory receiving the import was specified
- * when the editor was fetched.  (I.e, when EDITOR->open_root() is
- * called, it returns a directory baton for that directory, which is
- * not necessarily the root.)
- */
-static svn_error_t *
-import(const char *local_abspath,
-       const apr_array_header_t *new_entries,
-       const svn_delta_editor_t *editor,
-       void *edit_baton,
-       svn_depth_t depth,
-       apr_hash_t *excludes,
-       apr_hash_t *autoprops,
-       apr_array_header_t *local_ignores,
-       apr_array_header_t *global_ignores,
-       svn_boolean_t no_ignore,
-       svn_boolean_t no_autoprops,
-       svn_boolean_t ignore_unknown_node_types,
-       svn_client_import_filter_func_t filter_callback,
-       void *filter_baton,
-       svn_client_ctx_t *ctx,
-       apr_pool_t *pool)
-{
-  void *root_baton;
-  apr_array_header_t *batons = NULL;
-  const char *edit_path = "";
-  import_ctx_t *import_ctx = apr_pcalloc(pool, sizeof(*import_ctx));
-  const svn_io_dirent2_t *dirent;
-
-  import_ctx->autoprops = autoprops;
-  svn_magic__init(&import_ctx->magic_cookie, pool);
-
-  /* Get a root dir baton.  We pass an invalid revnum to open_root
-     to mean "base this on the youngest revision".  Should we have an
-     SVN_YOUNGEST_REVNUM defined for these purposes? */
-  SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM,
-                            pool, &root_baton));
-
-  /* Import a file or a directory tree. */
-  SVN_ERR(svn_io_stat_dirent(&dirent, local_abspath, FALSE, pool, pool));
-
-  /* Make the intermediate directory components necessary for properly
-     rooting our import source tree.  */
-  if (new_entries->nelts)
-    {
-      int i;
-
-      batons = apr_array_make(pool, new_entries->nelts, sizeof(void *));
-      for (i = 0; i < new_entries->nelts; i++)
-        {
-          const char *component = APR_ARRAY_IDX(new_entries, i, const char *);
-          edit_path = svn_relpath_join(edit_path, component, pool);
-
-          /* If this is the last path component, and we're importing a
-             file, then this component is the name of the file, not an
-             intermediate directory. */
-          if ((i == new_entries->nelts - 1) && (dirent->kind == svn_node_file))
-            break;
-
-          APR_ARRAY_PUSH(batons, void *) = root_baton;
-          SVN_ERR(editor->add_directory(edit_path,
-                                        root_baton,
-                                        NULL, SVN_INVALID_REVNUM,
-                                        pool, &root_baton));
-
-          /* Remember that the repository was modified */
-          import_ctx->repos_changed = TRUE;
-        }
-    }
-  else if (dirent->kind == svn_node_file)
-    {
-      return svn_error_create
-        (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-         _("New entry name required when importing a file"));
-    }
-
-  /* Note that there is no need to check whether PATH's basename is
-     the same name that we reserve for our administrative
-     subdirectories.  It would be strange -- though not illegal -- to
-     import the contents of a directory of that name, because the
-     directory's own name is not part of those contents.  Of course,
-     if something underneath it also has our reserved name, then we'll
-     error. */
-
-  if (dirent->kind == svn_node_file)
-    {
-      /* This code path ignores EXCLUDES and FILTER, but they don't make
-         much sense for a single file import anyway. */
-      svn_boolean_t ignores_match = FALSE;
-
-      if (!no_ignore)
-        ignores_match =
-          (svn_wc_match_ignore_list(local_abspath, global_ignores, pool)
-           || svn_wc_match_ignore_list(local_abspath, local_ignores, pool));
-
-      if (!ignores_match)
-        SVN_ERR(import_file(editor, root_baton, local_abspath, edit_path,
-                            dirent, import_ctx, ctx, pool));
-    }
-  else if (dirent->kind == svn_node_dir)
-    {
-      apr_hash_t *dirents;
-
-      /* If we are creating a new repository directory path to import to,
-         then we disregard any svn:ignore property. */
-      if (!no_ignore && new_entries->nelts)
-        local_ignores = NULL;
-
-      SVN_ERR(get_filtered_children(&dirents, local_abspath, excludes,
-                                    local_ignores, global_ignores,
-                                    filter_callback, filter_baton, ctx,
-                                    pool, pool));
-
-      SVN_ERR(import_children(local_abspath, edit_path, dirents, editor,
-                              root_baton, depth, excludes, global_ignores,
-                              no_ignore, no_autoprops,
-                              ignore_unknown_node_types, filter_callback,
-                              filter_baton, import_ctx, ctx, pool));
-
-    }
-  else if (dirent->kind == svn_node_none
-           || dirent->kind == svn_node_unknown)
-    {
-      return svn_error_createf(SVN_ERR_NODE_UNKNOWN_KIND, NULL,
-                               _("'%s' does not exist"),
-                               svn_dirent_local_style(local_abspath, pool));
-    }
-
-  /* Close up shop; it's time to go home. */
-  SVN_ERR(editor->close_directory(root_baton, pool));
-  if (batons && batons->nelts)
-    {
-      void **baton;
-      while ((baton = (void **) apr_array_pop(batons)))
-        {
-          SVN_ERR(editor->close_directory(*baton, pool));
-        }
-    }
-
-  if (import_ctx->repos_changed)
-    return editor->close_edit(edit_baton, pool);
-  else
-    return editor->abort_edit(edit_baton, pool);
-}
-
-
 struct capture_baton_t {
   svn_commit_callback2_t original_callback;
   void *original_baton;
@@ -866,209 +134,6 @@ get_ra_editor(const svn_delta_editor_t *
 
 /*** Public Interfaces. ***/
 
-svn_error_t *
-svn_client_import5(const char *path,
-                   const char *url,
-                   svn_depth_t depth,
-                   svn_boolean_t no_ignore,
-                   svn_boolean_t no_autoprops,
-                   svn_boolean_t ignore_unknown_node_types,
-                   const apr_hash_t *revprop_table,
-                   svn_client_import_filter_func_t filter_callback,
-                   void *filter_baton,
-                   svn_commit_callback2_t commit_callback,
-                   void *commit_baton,
-                   svn_client_ctx_t *ctx,
-                   apr_pool_t *scratch_pool)
-{
-  svn_error_t *err = SVN_NO_ERROR;
-  const char *log_msg = "";
-  const svn_delta_editor_t *editor;
-  void *edit_baton;
-  svn_ra_session_t *ra_session;
-  apr_hash_t *excludes = apr_hash_make(scratch_pool);
-  svn_node_kind_t kind;
-  const char *local_abspath;
-  apr_array_header_t *new_entries = apr_array_make(scratch_pool, 4,
-                                                   sizeof(const char *));
-  const char *temp;
-  const char *dir;
-  apr_hash_t *commit_revprops;
-  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-  apr_hash_t *autoprops = NULL;
-  apr_array_header_t *global_ignores;
-  apr_hash_t *local_ignores_hash;
-  apr_array_header_t *local_ignores_arr;
-
-  if (svn_path_is_url(path))
-    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
-                             _("'%s' is not a local path"), path);
-
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
-
-  /* Create a new commit item and add it to the array. */
-  if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx))
-    {
-      /* If there's a log message gatherer, create a temporary commit
-         item array solely to help generate the log message.  The
-         array is not used for the import itself. */
-      svn_client_commit_item3_t *item;
-      const char *tmp_file;
-      apr_array_header_t *commit_items
-        = apr_array_make(scratch_pool, 1, sizeof(item));
-
-      item = svn_client_commit_item3_create(scratch_pool);
-      item->path = apr_pstrdup(scratch_pool, path);
-      item->state_flags = SVN_CLIENT_COMMIT_ITEM_ADD;
-      APR_ARRAY_PUSH(commit_items, svn_client_commit_item3_t *) = item;
-
-      SVN_ERR(svn_client__get_log_msg(&log_msg, &tmp_file, commit_items,
-                                      ctx, scratch_pool));
-      if (! log_msg)
-        return SVN_NO_ERROR;
-      if (tmp_file)
-        {
-          const char *abs_path;
-          SVN_ERR(svn_dirent_get_absolute(&abs_path, tmp_file, scratch_pool));
-          apr_hash_set(excludes, abs_path, APR_HASH_KEY_STRING, (void *)1);
-        }
-    }
-
-  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
-
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url, NULL,
-                                               NULL, FALSE, TRUE, ctx,
-                                               scratch_pool));
-
-  /* Figure out all the path components we need to create just to have
-     a place to stick our imported tree. */
-  SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind,
-                            iterpool));
-
-  /* We can import into directories, but if a file already exists, that's
-     an error. */
-  if (kind == svn_node_file)
-    return svn_error_createf
-      (SVN_ERR_ENTRY_EXISTS, NULL,
-       _("Path '%s' already exists"), url);
-
-  while (kind == svn_node_none)
-    {
-      svn_pool_clear(iterpool);
-
-      svn_uri_split(&temp, &dir, url, scratch_pool);
-      APR_ARRAY_PUSH(new_entries, const char *) = dir;
-      url = temp;
-      SVN_ERR(svn_ra_reparent(ra_session, url, iterpool));
-
-      SVN_ERR(svn_ra_check_path(ra_session, "", SVN_INVALID_REVNUM, &kind,
-                                iterpool));
-    }
-
-  /* Reverse the order of the components we added to our NEW_ENTRIES array. */
-  if (new_entries->nelts)
-    {
-      int i, j;
-      const char *component;
-      for (i = 0; i < (new_entries->nelts / 2); i++)
-        {
-          j = new_entries->nelts - i - 1;
-          component =
-            APR_ARRAY_IDX(new_entries, i, const char *);
-          APR_ARRAY_IDX(new_entries, i, const char *) =
-            APR_ARRAY_IDX(new_entries, j, const char *);
-          APR_ARRAY_IDX(new_entries, j, const char *) =
-            component;
-        }
-    }
-
-  /* The repository doesn't know about the reserved administrative
-     directory. */
-  if (new_entries->nelts
-      /* What's this, what's this?  This assignment is here because we
-         use the value to construct the error message just below.  It
-         may not be aesthetically pleasing, but it's less ugly than
-         calling APR_ARRAY_IDX twice. */
-      && svn_wc_is_adm_dir(temp = APR_ARRAY_IDX(new_entries,
-                                                new_entries->nelts - 1,
-                                                const char *),
-                           scratch_pool))
-    return svn_error_createf
-      (SVN_ERR_CL_ADM_DIR_RESERVED, NULL,
-       _("'%s' is a reserved name and cannot be imported"),
-       svn_dirent_local_style(temp, scratch_pool));
-
-  SVN_ERR(svn_client__ensure_revprop_table(&commit_revprops, revprop_table,
-                                           log_msg, ctx, scratch_pool));
-
-  /* Fetch RA commit editor. */
-  SVN_ERR(svn_ra__register_editor_shim_callbacks(ra_session,
-                        svn_client__get_shim_callbacks(ctx->wc_ctx,
-                                                       NULL, scratch_pool)));
-  SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
-                                    commit_revprops, commit_callback,
-                                    commit_baton, NULL, TRUE,
-                                    scratch_pool));
-
-  /* Get inherited svn:auto-props, svn:global-ignores, and
-     svn:ignores for the location we are importing to. */
-  if (!no_autoprops)
-    SVN_ERR(svn_client__get_all_auto_props(&autoprops, url, ctx,
-                                           scratch_pool, iterpool));
-  if (no_ignore)
-    {
-      global_ignores = NULL;
-      local_ignores_arr = NULL;
-    }
-  else
-    {
-      svn_opt_revision_t rev;
-      apr_array_header_t *config_ignores;
-
-      SVN_ERR(svn_client__get_inherited_ignores(&global_ignores, url, ctx,
-                                                scratch_pool, iterpool));
-      SVN_ERR(svn_wc_get_default_ignores(&config_ignores, ctx->config,
-                                         scratch_pool));
-      global_ignores = apr_array_append(scratch_pool, global_ignores,
-                                        config_ignores);
-
-      rev.kind = svn_opt_revision_head;
-      SVN_ERR(svn_client_propget5(&local_ignores_hash, NULL, SVN_PROP_IGNORE, url,
-                                  &rev, &rev, NULL, svn_depth_empty, NULL, ctx,
-                                  scratch_pool, scratch_pool));
-      local_ignores_arr = apr_array_make(scratch_pool, 1, sizeof(const char *));
-
-      if (apr_hash_count(local_ignores_hash))
-        {
-          svn_string_t *propval = apr_hash_get(local_ignores_hash, url,
-                                               APR_HASH_KEY_STRING);
-          if (propval)
-            {
-              svn_cstring_split_append(local_ignores_arr, propval->data,
-                                       "\n\r\t\v ", FALSE, scratch_pool);
-            }
-        }
-    }
-
-  /* If an error occurred during the commit, abort the edit and return
-     the error.  We don't even care if the abort itself fails.  */
-  if ((err = import(local_abspath, new_entries, editor, edit_baton,
-                    depth, excludes, autoprops, local_ignores_arr,
-                    global_ignores, no_ignore, no_autoprops,
-                    ignore_unknown_node_types, filter_callback,
-                    filter_baton, ctx, iterpool)))
-    {
-      return svn_error_compose_create(
-                    err,
-                    editor->abort_edit(edit_baton, iterpool));
-    }
-
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
-
 static svn_error_t *
 reconcile_errors(svn_error_t *commit_err,
                  svn_error_t *unlock_err,
@@ -1286,8 +351,8 @@ determine_lock_targets(apr_array_header_
       target_abspath = svn_dirent_join(base_abspath, target_relpath,
                                        scratch_pool);
 
-      err = svn_wc__get_wc_root(&wcroot_abspath, wc_ctx, target_abspath,
-                                iterpool, iterpool);
+      err = svn_wc__get_wcroot(&wcroot_abspath, wc_ctx, target_abspath,
+                               iterpool, iterpool);
 
       if (err)
         {
@@ -1432,25 +497,6 @@ append_externals_as_explicit_targets(apr
       /* Don't recurse. */
       return SVN_NO_ERROR;
     }
-  else if (depth != svn_depth_infinity)
-    {
-      include_dir_externals = FALSE;
-      /* We slip in dir externals as explicit targets. When we do that,
-       * depth_immediates should become depth_empty for dir externals targets.
-       * But adding the dir external to the list of targets makes it get
-       * handled with depth_immediates itself, and thus will also include the
-       * immediate children of the dir external. So do dir externals only with
-       * depth_infinity or not at all.
-       * ### TODO: Maybe rework this (and svn_client_commit6()) into separate
-       * ### target lists, "duplicating" REL_TARGETS: one for the user's
-       * ### targets and one for the overlayed externals targets, and pass an
-       * ### appropriate depth for the externals targets in a separate call to
-       * ### svn_client__harvest_committables(). The only gain is correct
-       * ### handling of this very specific case: during 'svn commit
-       * ### --depth=immediates --include-externals', commit dir externals
-       * ### (only immediate children of a target) with depth_empty instead of
-       * ### not at all. No other effect. So not doing that for now. */
-    }
 
   /* Iterate *and* grow REL_TARGETS at the same time. */
   rel_targets_nelts_fixed = rel_targets->nelts;
@@ -1543,6 +589,7 @@ svn_client_commit6(const apr_array_heade
   apr_pool_t *iterpool = svn_pool_create(pool);
   const char *current_abspath;
   const char *notify_prefix;
+  int depth_empty_after = -1;
   int i;
 
   SVN_ERR_ASSERT(depth != svn_depth_unknown && depth != svn_depth_exclude);
@@ -1573,11 +620,20 @@ svn_client_commit6(const apr_array_heade
   if (rel_targets->nelts == 0)
     APR_ARRAY_PUSH(rel_targets, const char *) = "";
 
-  SVN_ERR(append_externals_as_explicit_targets(rel_targets, base_abspath,
-                                               include_file_externals,
-                                               include_dir_externals,
-                                               depth, ctx,
-                                               pool, pool));
+  if (include_file_externals || include_dir_externals)
+    {
+      if (depth != svn_depth_unknown && depth != svn_depth_infinity)
+        {
+          /* All targets after this will be handled as depth empty */
+          depth_empty_after = rel_targets->nelts;
+        }
+
+      SVN_ERR(append_externals_as_explicit_targets(rel_targets, base_abspath,
+                                                   include_file_externals,
+                                                   include_dir_externals,
+                                                   depth, ctx,
+                                                   pool, pool));
+    }
 
   SVN_ERR(determine_lock_targets(&lock_targets, ctx->wc_ctx, base_abspath,
                                  rel_targets, pool, iterpool));
@@ -1643,6 +699,7 @@ svn_client_commit6(const apr_array_heade
                                                     &lock_tokens,
                                                     base_abspath,
                                                     rel_targets,
+                                                    depth_empty_after,
                                                     depth,
                                                     ! keep_locks,
                                                     changelists,
@@ -1963,25 +1020,3 @@ svn_client_commit6(const apr_array_heade
   return svn_error_trace(reconcile_errors(cmt_err, unlock_err, bump_err,
                                           pool));
 }
-
-svn_error_t *
-svn_client_commit5(const apr_array_header_t *targets,
-                   svn_depth_t depth,
-                   svn_boolean_t keep_locks,
-                   svn_boolean_t keep_changelists,
-                   svn_boolean_t commit_as_operations,
-                   const apr_array_header_t *changelists,
-                   const apr_hash_t *revprop_table,
-                   svn_commit_callback2_t commit_callback,
-                   void *commit_baton,
-                   svn_client_ctx_t *ctx,
-                   apr_pool_t *pool)
-{
-  return svn_client_commit6(targets, depth, keep_locks, keep_changelists,
-                            commit_as_operations,
-                            TRUE,  /* include_file_externals */
-                            FALSE, /* include_dir_externals */
-                            changelists, revprop_table, commit_callback,
-                            commit_baton, ctx, pool);
-}
-

Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/commit_util.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/commit_util.c Mon Feb  4 20:48:05 2013
@@ -290,8 +290,8 @@ bail_on_tree_conflicted_ancestor(svn_wc_
 {
   const char *wcroot_abspath;
 
-  SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, wc_ctx, local_abspath,
-                              scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, wc_ctx, local_abspath,
+                             scratch_pool, scratch_pool));
 
   local_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
@@ -1082,6 +1082,7 @@ svn_client__harvest_committables(svn_cli
                                  apr_hash_t **lock_tokens,
                                  const char *base_dir_abspath,
                                  const apr_array_header_t *targets,
+                                 int depth_empty_start,
                                  svn_depth_t depth,
                                  svn_boolean_t just_locked,
                                  const apr_array_header_t *changelists,
@@ -1154,6 +1155,10 @@ svn_client__harvest_committables(svn_cli
                                                ctx->notify_baton2,
                                                iterpool));
 
+      /* Are the remaining items externals with depth empty? */
+      if (i == depth_empty_start)
+        depth = svn_depth_empty;
+
       SVN_ERR(harvest_committables(target_abspath,
                                    *committables, *lock_tokens,
                                    NULL /* COPY_MODE_RELPATH */,

Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/copy.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/copy.c Mon Feb  4 20:48:05 2013
@@ -245,6 +245,7 @@ do_wc_to_wc_moves_with_locks2(svn_client
                               svn_boolean_t lock_src,
                               svn_boolean_t lock_dst,
                               svn_boolean_t allow_mixed_revisions,
+                              svn_boolean_t metadata_only,
                               svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool)
 {
@@ -254,7 +255,7 @@ do_wc_to_wc_moves_with_locks2(svn_client
                                 scratch_pool);
 
   SVN_ERR(svn_wc__move2(ctx->wc_ctx, pair->src_abspath_or_url,
-                        dst_abspath, FALSE /* metadata_only */,
+                        dst_abspath, metadata_only,
                         allow_mixed_revisions,
                         ctx->cancel_func, ctx->cancel_baton,
                         ctx->notify_func2, ctx->notify_baton2,
@@ -270,18 +271,21 @@ do_wc_to_wc_moves_with_locks1(svn_client
                               svn_boolean_t lock_src,
                               svn_boolean_t lock_dst,
                               svn_boolean_t allow_mixed_revisions,
+                              svn_boolean_t metadata_only,
                               svn_client_ctx_t *ctx,
                               apr_pool_t *scratch_pool)
 {
   if (lock_dst)
     SVN_WC__CALL_WITH_WRITE_LOCK(
       do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src,
-                                    lock_dst, allow_mixed_revisions, ctx,
-                                    scratch_pool),
+                                    lock_dst, allow_mixed_revisions,
+                                    metadata_only,
+                                    ctx, scratch_pool),
       ctx->wc_ctx, dst_parent_abspath, FALSE, scratch_pool);
   else
     SVN_ERR(do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src,
                                           lock_dst, allow_mixed_revisions,
+                                          metadata_only,
                                           ctx, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -293,6 +297,7 @@ static svn_error_t *
 do_wc_to_wc_moves(const apr_array_header_t *copy_pairs,
                   const char *dst_path,
                   svn_boolean_t allow_mixed_revisions,
+                  svn_boolean_t metadata_only,
                   svn_client_ctx_t *ctx,
                   apr_pool_t *pool)
 {
@@ -348,13 +353,16 @@ do_wc_to_wc_moves(const apr_array_header
         SVN_WC__CALL_WITH_WRITE_LOCK(
           do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath,
                                         lock_src, lock_dst,
-                                        allow_mixed_revisions, ctx, iterpool),
+                                        allow_mixed_revisions,
+                                        metadata_only,
+                                        ctx, iterpool),
           ctx->wc_ctx, src_parent_abspath,
           FALSE, iterpool);
       else
         SVN_ERR(do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath,
                                               lock_src, lock_dst,
                                               allow_mixed_revisions,
+                                              metadata_only,
                                               ctx, iterpool));
 
     }
@@ -1538,58 +1546,73 @@ repos_to_wc_copy_single(svn_client__copy
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
 
-  if (pair->src_kind == svn_node_dir)
+  if (!same_repositories && ctx->notify_func2)
     {
-      svn_boolean_t sleep_needed = FALSE;
-      const char *tmpdir_abspath, *tmp_abspath;
+      svn_wc_notify_t *notify;
+      notify = svn_wc_create_notify_url(
+                            pair->src_abspath_or_url,
+                            svn_wc_notify_foreign_copy_begin,
+                            pool);
+      notify->kind = pair->src_kind;
+      ctx->notify_func2(ctx->notify_baton2, notify, pool);
 
-      /* Find a temporary location in which to check out the copy source. */
-      SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
-                                 pool, pool));
-                                 
-      SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
-                                       svn_io_file_del_on_close, pool, pool));
-
-      /* Make a new checkout of the requested source. While doing so,
-       * resolve pair->src_revnum to an actual revision number in case it
-       * was until now 'invalid' meaning 'head'.  Ask this function not to
-       * sleep for timestamps, by passing a sleep_needed output param.
-       * Send notifications for all nodes except the root node, and adjust
-       * them to refer to the destination rather than this temporary path. */
-      {
-        svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
-        void *old_notify_baton2 = ctx->notify_baton2;
-        struct notification_adjust_baton nb;
-        svn_error_t *err;
-
-        nb.inner_func = ctx->notify_func2;
-        nb.inner_baton = ctx->notify_baton2;
-        nb.checkout_abspath = tmp_abspath;
-        nb.final_abspath = dst_abspath;
-        ctx->notify_func2 = notification_adjust_func;
-        ctx->notify_baton2 = &nb;
-
-        err = svn_client__checkout_internal(&pair->src_revnum,
-                                            pair->src_original,
-                                            tmp_abspath,
-                                            &pair->src_peg_revision,
-                                            &pair->src_op_revision,
-                                            svn_depth_infinity,
-                                            ignore_externals, FALSE,
-                                            &sleep_needed, ctx, pool);
+      /* Allow a theoretical cancel to get through. */
+      if (ctx->cancel_func)
+        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+    }
+
+  if (pair->src_kind == svn_node_dir)
+    {
+      if (same_repositories)
+        {
+          svn_boolean_t sleep_needed = FALSE;
+          const char *tmpdir_abspath, *tmp_abspath;
 
-        ctx->notify_func2 = old_notify_func2;
-        ctx->notify_baton2 = old_notify_baton2;
+          /* Find a temporary location in which to check out the copy source. */
+          SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
+                                     pool, pool));
+                                     
+          SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
+                                           svn_io_file_del_on_close, pool, pool));
+
+          /* Make a new checkout of the requested source. While doing so,
+           * resolve pair->src_revnum to an actual revision number in case it
+           * was until now 'invalid' meaning 'head'.  Ask this function not to
+           * sleep for timestamps, by passing a sleep_needed output param.
+           * Send notifications for all nodes except the root node, and adjust
+           * them to refer to the destination rather than this temporary path. */
+          {
+            svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
+            void *old_notify_baton2 = ctx->notify_baton2;
+            struct notification_adjust_baton nb;
+            svn_error_t *err;
+          
+            nb.inner_func = ctx->notify_func2;
+            nb.inner_baton = ctx->notify_baton2;
+            nb.checkout_abspath = tmp_abspath;
+            nb.final_abspath = dst_abspath;
+            ctx->notify_func2 = notification_adjust_func;
+            ctx->notify_baton2 = &nb;
+          
+            err = svn_client__checkout_internal(&pair->src_revnum,
+                                                pair->src_original,
+                                                tmp_abspath,
+                                                &pair->src_peg_revision,
+                                                &pair->src_op_revision,
+                                                svn_depth_infinity,
+                                                ignore_externals, FALSE,
+                                                &sleep_needed, ctx, pool);
+          
+            ctx->notify_func2 = old_notify_func2;
+            ctx->notify_baton2 = old_notify_baton2;
 
-        SVN_ERR(err);
-      }
+            SVN_ERR(err);
+          }
 
       /* Schedule dst_path for addition in parent, with copy history.
          Don't send any notification here.
          Then remove the temporary checkout's .svn dir in preparation for
          moving the rest of it into the final destination. */
-      if (same_repositories)
-        {
           SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath,
                                TRUE /* metadata_only */,
                                ctx->cancel_func, ctx->cancel_baton,
@@ -1608,21 +1631,16 @@ repos_to_wc_copy_single(svn_client__copy
         }
       else
         {
-          /* ### We want to schedule this as a simple add, or even better
-             a copy from a foreign repos, but we don't yet have the
-             WC APIs to do that, so we will just move the whole WC into
-             place as a disjoint, nested WC. */
-
-          /* Move the working copy to where it is expected. */
-          SVN_ERR(svn_wc__rename_wc(ctx->wc_ctx, tmp_abspath, dst_abspath,
-                                    pool));
-
-          svn_io_sleep_for_timestamps(dst_abspath, pool);
+          SVN_ERR(svn_client__copy_foreign(pair->src_abspath_or_url,
+                                           dst_abspath,
+                                           &pair->src_peg_revision,
+                                           &pair->src_op_revision,
+                                           svn_depth_infinity,
+                                           FALSE /* make_parents */,
+                                           TRUE /* already_locked */,
+                                           ctx, pool));
 
-          return svn_error_createf(
-             SVN_ERR_UNSUPPORTED_FEATURE, NULL,
-             _("Source URL '%s' is from foreign repository; "
-               "leaving it as a disjoint WC"), pair->src_abspath_or_url);
+          return SVN_NO_ERROR;
         }
     } /* end directory case */
 
@@ -1640,6 +1658,10 @@ repos_to_wc_copy_single(svn_client__copy
       SVN_ERR(svn_ra_get_file(ra_session, src_rel, pair->src_revnum,
                               new_base_contents,
                               &pair->src_revnum, &new_props, pool));
+
+      if (new_props && ! same_repositories)
+        apr_hash_set(new_props, SVN_PROP_MERGEINFO, APR_HASH_KEY_STRING, NULL);
+
       SVN_ERR(svn_wc_add_repos_file4(
          ctx->wc_ctx, dst_abspath,
          new_base_contents, NULL, new_props, NULL,
@@ -1876,6 +1898,7 @@ try_copy(const apr_array_header_t *sourc
          const char *dst_path_in,
          svn_boolean_t is_move,
          svn_boolean_t allow_mixed_revisions,
+         svn_boolean_t metadata_only,
          svn_boolean_t make_parents,
          svn_boolean_t ignore_externals,
          const apr_hash_t *revprop_table,
@@ -2167,9 +2190,14 @@ try_copy(const apr_array_header_t *sourc
       if (is_move)
         return svn_error_trace(do_wc_to_wc_moves(copy_pairs, dst_path_in,
                                                  allow_mixed_revisions,
+                                                 metadata_only,
                                                  ctx, pool));
       else
-        return svn_error_trace(do_wc_to_wc_copies(copy_pairs, ctx, pool));
+        {
+          /* We ignore these values, so assert the default value */
+          SVN_ERR_ASSERT(allow_mixed_revisions && !metadata_only);
+          return svn_error_trace(do_wc_to_wc_copies(copy_pairs, ctx, pool));
+        }
     }
   else if ((! srcs_are_urls) && (dst_is_url))
     {
@@ -2217,6 +2245,7 @@ svn_client_copy6(const apr_array_header_
   err = try_copy(sources, dst_path,
                  FALSE /* is_move */,
                  TRUE /* allow_mixed_revisions */,
+                 FALSE /* metadata_only */,
                  make_parents,
                  ignore_externals,
                  revprop_table,
@@ -2249,6 +2278,7 @@ svn_client_copy6(const apr_array_header_
                          : svn_dirent_join(dst_path, src_basename, subpool),
                      FALSE /* is_move */,
                      TRUE /* allow_mixed_revisions */,
+                     FALSE /* metadata_only */,
                      make_parents,
                      ignore_externals,
                      revprop_table,
@@ -2268,6 +2298,7 @@ svn_client_move7(const apr_array_header_
                  svn_boolean_t move_as_child,
                  svn_boolean_t make_parents,
                  svn_boolean_t allow_mixed_revisions,
+                 svn_boolean_t metadata_only,
                  const apr_hash_t *revprop_table,
                  svn_commit_callback2_t commit_callback,
                  void *commit_baton,
@@ -2302,8 +2333,9 @@ svn_client_move7(const apr_array_header_
   err = try_copy(sources, dst_path,
                  TRUE /* is_move */,
                  allow_mixed_revisions,
+                 metadata_only,
                  make_parents,
-                 FALSE,
+                 FALSE /* ignore_externals */,
                  revprop_table,
                  commit_callback, commit_baton,
                  ctx,
@@ -2333,8 +2365,9 @@ svn_client_move7(const apr_array_header_
                          : svn_dirent_join(dst_path, src_basename, pool),
                      TRUE /* is_move */,
                      allow_mixed_revisions,
+                     metadata_only,
                      make_parents,
-                     FALSE,
+                     FALSE /* ignore_externals */,
                      revprop_table,
                      commit_callback, commit_baton,
                      ctx,

Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/delete.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/delete.c Mon Feb  4 20:48:05 2013
@@ -46,36 +46,47 @@
 
 /*** Code. ***/
 
+/* Baton for find_undeletables */
+struct can_delete_baton_t
+{
+  const char *root_abspath;
+  svn_boolean_t target_missing;
+};
 
 /* An svn_wc_status_func4_t callback function for finding
    status structures which are not safely deletable. */
 static svn_error_t *
 find_undeletables(void *baton,
-                  const char *path,
+                  const char *local_abspath,
                   const svn_wc_status3_t *status,
                   apr_pool_t *pool)
 {
+  if (status->node_status == svn_wc_status_missing)
+    {
+      struct can_delete_baton_t *cdt = baton;
+
+      if (strcmp(cdt->root_abspath, local_abspath) == 0)
+        cdt->target_missing = TRUE;
+    }
+
   /* Check for error-ful states. */
   if (status->node_status == svn_wc_status_obstructed)
     return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
                              _("'%s' is in the way of the resource "
                                "actually under version control"),
-                             svn_dirent_local_style(path, pool));
+                             svn_dirent_local_style(local_abspath, pool));
   else if (! status->versioned)
     return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL,
                              _("'%s' is not under version control"),
-                             svn_dirent_local_style(path, pool));
+                             svn_dirent_local_style(local_abspath, pool));
 
-  else if ((status->node_status != svn_wc_status_normal
-            && status->node_status != svn_wc_status_deleted
-            && status->node_status != svn_wc_status_missing)
-           ||
-           (status->prop_status != svn_wc_status_none
-            && status->prop_status != svn_wc_status_normal))
+  else if (status->node_status != svn_wc_status_normal
+           && status->node_status != svn_wc_status_deleted
+           && status->node_status != svn_wc_status_missing)
     return svn_error_createf(SVN_ERR_CLIENT_MODIFIED, NULL,
                              _("'%s' has local modifications -- commit or "
                                "revert them first"),
-                             svn_dirent_local_style(path, pool));
+                             svn_dirent_local_style(local_abspath, pool));
 
   return SVN_NO_ERROR;
 }
@@ -86,13 +97,15 @@ find_undeletables(void *baton,
    command.  CTX is used for the client's config options.  POOL is
    used for all temporary allocations. */
 static svn_error_t *
-can_delete_node(const char *local_abspath,
+can_delete_node(svn_boolean_t *target_missing,
+                const char *local_abspath,
                 svn_client_ctx_t *ctx,
                 apr_pool_t *scratch_pool)
 {
   svn_node_kind_t external_kind;
   const char *defining_abspath;
   apr_array_header_t *ignores;
+  struct can_delete_baton_t cdt;
 
   /* A file external should not be deleted since the file external is
      implemented as a switched file and it would delete the file the
@@ -123,17 +136,25 @@ can_delete_node(const char *local_abspat
 
   SVN_ERR(svn_wc_get_default_ignores(&ignores, ctx->config, scratch_pool));
 
-  return svn_error_trace(svn_wc_walk_status(ctx->wc_ctx,
-                                            local_abspath,
-                                            svn_depth_infinity,
-                                            FALSE /* get_all */,
-                                            FALSE /* no_ignore */,
-                                            FALSE /* ignore_text_mod */,
-                                            ignores,
-                                            find_undeletables, NULL,
-                                            ctx->cancel_func,
-                                            ctx->cancel_baton,
-                                            scratch_pool));
+  cdt.root_abspath = local_abspath;
+  cdt.target_missing = FALSE;
+
+  SVN_ERR(svn_wc_walk_status(ctx->wc_ctx,
+                             local_abspath,
+                             svn_depth_infinity,
+                             FALSE /* get_all */,
+                             FALSE /* no_ignore */,
+                             FALSE /* ignore_text_mod */,
+                             ignores,
+                             find_undeletables, &cdt,
+                             ctx->cancel_func,
+                             ctx->cancel_baton,
+                             scratch_pool));
+
+  if (target_missing)
+    *target_missing = cdt.target_missing;
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -318,7 +339,7 @@ delete_urls_multi_repos(const apr_array_
 }
 
 svn_error_t *
-svn_client__wc_delete(const char *path,
+svn_client__wc_delete(const char *local_abspath,
                       svn_boolean_t force,
                       svn_boolean_t dry_run,
                       svn_boolean_t keep_local,
@@ -327,18 +348,20 @@ svn_client__wc_delete(const char *path,
                       svn_client_ctx_t *ctx,
                       apr_pool_t *pool)
 {
-  const char *local_abspath;
+  svn_boolean_t target_missing = FALSE;
 
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   if (!force && !keep_local)
     /* Verify that there are no "awkward" files */
-    SVN_ERR(can_delete_node(local_abspath, ctx, pool));
+    SVN_ERR(can_delete_node(&target_missing, local_abspath, ctx, pool));
 
   if (!dry_run)
     /* Mark the entry for commit deletion and perform wc deletion */
     return svn_error_trace(svn_wc_delete4(ctx->wc_ctx, local_abspath,
-                                          keep_local, TRUE,
+                                          keep_local || target_missing
+                                                            /*keep_local */,
+                                          TRUE /* delete_unversioned */,
                                           ctx->cancel_func, ctx->cancel_baton,
                                           notify_func, notify_baton, pool));
 
@@ -356,30 +379,43 @@ svn_client__wc_delete_many(const apr_arr
                            apr_pool_t *pool)
 {
   int i;
-  apr_array_header_t *abs_targets;
+  svn_boolean_t has_non_missing = FALSE;
 
-  abs_targets = apr_array_make(pool, targets->nelts, sizeof(const char *));
   for (i = 0; i < targets->nelts; i++)
     {
-      const char *path = APR_ARRAY_IDX(targets, i, const char *);
-      const char *local_abspath;
+      const char *local_abspath = APR_ARRAY_IDX(targets, i, const char *);
 
-      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-      APR_ARRAY_PUSH(abs_targets, const char *) = local_abspath;
+      SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
       if (!force && !keep_local)
-        /* Verify that there are no "awkward" files */
-        SVN_ERR(can_delete_node(local_abspath, ctx, pool));
+        {
+          svn_boolean_t missing;
+          /* Verify that there are no "awkward" files */
+
+          SVN_ERR(can_delete_node(&missing, local_abspath, ctx, pool));
+
+          if (! missing)
+            has_non_missing = TRUE;
+        }
+      else
+        has_non_missing = TRUE;
     }
 
   if (!dry_run)
-    /* Mark the entry for commit deletion and perform wc deletion */
-    return svn_error_trace(svn_wc__delete_many(ctx->wc_ctx, abs_targets,
-                                               keep_local, TRUE,
-                                               ctx->cancel_func,
-                                               ctx->cancel_baton,
-                                               notify_func, notify_baton,
-                                               pool));
+    {
+      /* Mark the entry for commit deletion and perform wc deletion */
+
+      /* If none of the targets exists, pass keep local TRUE, to avoid
+         deleting case-different files. Detecting this in the generic case
+         from the delete code is expensive */
+      return svn_error_trace(svn_wc__delete_many(ctx->wc_ctx, targets,
+                                                 keep_local || !has_non_missing,
+                                                 TRUE /* delete_unversioned_target */,
+                                                 ctx->cancel_func,
+                                                 ctx->cancel_baton,
+                                                 notify_func, notify_baton,
+                                                 pool));
+    }
 
   return SVN_NO_ERROR;
 }
@@ -435,8 +471,8 @@ svn_client_delete4(const apr_array_heade
                                           APR_ARRAY_IDX(paths, i,
                                                         const char *),
                                           pool));
-          SVN_ERR(svn_wc__get_wc_root(&wcroot_abspath, ctx->wc_ctx,
-                                      local_abspath, pool, iterpool));
+          SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx,
+                                     local_abspath, pool, iterpool));
           targets = apr_hash_get(wcroots, wcroot_abspath,
                                  APR_HASH_KEY_STRING);
           if (targets == NULL)

Modified: subversion/branches/fsfs-format7/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsfs-format7/subversion/libsvn_client/deprecated.c?rev=1442344&r1=1442343&r2=1442344&view=diff
==============================================================================
--- subversion/branches/fsfs-format7/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/fsfs-format7/subversion/libsvn_client/deprecated.c Mon Feb  4 20:48:05 2013
@@ -512,6 +512,26 @@ downgrade_commit_copied_notify_func(void
     b->orig_notify_func2(b->orig_notify_baton2, notify, pool);
 }
 
+svn_error_t *
+svn_client_commit5(const apr_array_header_t *targets,
+                   svn_depth_t depth,
+                   svn_boolean_t keep_locks,
+                   svn_boolean_t keep_changelists,
+                   svn_boolean_t commit_as_operations,
+                   const apr_array_header_t *changelists,
+                   const apr_hash_t *revprop_table,
+                   svn_commit_callback2_t commit_callback,
+                   void *commit_baton,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool)
+{
+  return svn_client_commit6(targets, depth, keep_locks, keep_changelists,
+                            commit_as_operations,
+                            FALSE,  /* include_file_externals */
+                            FALSE, /* include_dir_externals */
+                            changelists, revprop_table, commit_callback,
+                            commit_baton, ctx, pool);
+}
 
 svn_error_t *
 svn_client_commit4(svn_commit_info_t **commit_info_p,
@@ -724,7 +744,8 @@ svn_client_move6(const apr_array_header_
 {
   return svn_error_trace(svn_client_move7(src_paths, dst_path,
                                           move_as_child, make_parents,
-                                          TRUE, /* allow_mixed_revisions */
+                                          TRUE /* allow_mixed_revisions */,
+                                          FALSE /* metadata_only */,
                                           revprop_table,
                                           commit_callback, commit_baton,
                                           ctx, pool));
@@ -916,9 +937,11 @@ svn_client_diff5(const apr_array_header_
 
   return svn_client_diff6(diff_options, path1, revision1, path2,
                           revision2, relative_to_dir, depth,
-                          ignore_ancestry, no_diff_deleted,
-                          show_copies_as_adds, ignore_content_type, FALSE,
-                          FALSE, use_git_diff_format, header_encoding,
+                          ignore_ancestry, FALSE /* no_diff_added */,
+                          no_diff_deleted, show_copies_as_adds,
+                          ignore_content_type, FALSE /* ignore_properties */,
+                          FALSE /* properties_only */, use_git_diff_format,
+                          header_encoding,
                           outstream, errstream, changelists, ctx, pool);
 }
 
@@ -1042,11 +1065,12 @@ svn_client_diff_peg5(const apr_array_hea
                               relative_to_dir,
                               depth,
                               ignore_ancestry,
+                              FALSE /* no_diff_added */,
                               no_diff_deleted,
                               show_copies_as_adds,
                               ignore_content_type,
-                              FALSE,
-                              FALSE,
+                              FALSE /* ignore_properties */,
+                              FALSE /* properties_only */,
                               use_git_diff_format,
                               header_encoding,
                               outstream,
@@ -1606,6 +1630,34 @@ svn_client_log(const apr_array_header_t 
 /*** From merge.c ***/
 
 svn_error_t *
+svn_client_merge4(const char *source1,
+                  const svn_opt_revision_t *revision1,
+                  const char *source2,
+                  const svn_opt_revision_t *revision2,
+                  const char *target_wcpath,
+                  svn_depth_t depth,
+                  svn_boolean_t ignore_ancestry,
+                  svn_boolean_t force_delete,
+                  svn_boolean_t record_only,
+                  svn_boolean_t dry_run,
+                  svn_boolean_t allow_mixed_rev,
+                  const apr_array_header_t *merge_options,
+                  svn_client_ctx_t *ctx,
+                  apr_pool_t *pool)
+{
+  SVN_ERR(svn_client_merge5(source1, revision1,
+                            source2, revision2,
+                            target_wcpath,
+                            depth,
+                            ignore_ancestry /*ignore_mergeinfo*/,
+                            ignore_ancestry /*diff_ignore_ancestry*/,
+                            force_delete, record_only,
+                            dry_run, allow_mixed_rev,
+                            merge_options, ctx, pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_client_merge3(const char *source1,
                   const svn_opt_revision_t *revision1,
                   const char *source2,
@@ -1666,6 +1718,34 @@ svn_client_merge(const char *source1,
 }
 
 svn_error_t *
+svn_client_merge_peg4(const char *source_path_or_url,
+                      const apr_array_header_t *ranges_to_merge,
+                      const svn_opt_revision_t *source_peg_revision,
+                      const char *target_wcpath,
+                      svn_depth_t depth,
+                      svn_boolean_t ignore_ancestry,
+                      svn_boolean_t force_delete,
+                      svn_boolean_t record_only,
+                      svn_boolean_t dry_run,
+                      svn_boolean_t allow_mixed_rev,
+                      const apr_array_header_t *merge_options,
+                      svn_client_ctx_t *ctx,
+                      apr_pool_t *pool)
+{
+  SVN_ERR(svn_client_merge_peg5(source_path_or_url,
+                                ranges_to_merge,
+                                source_peg_revision,
+                                target_wcpath,
+                                depth,
+                                ignore_ancestry /*ignore_mergeinfo*/,
+                                ignore_ancestry /*diff_ignore_ancestry*/,
+                                force_delete, record_only,
+                                dry_run, allow_mixed_rev,
+                                merge_options, ctx, pool));
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
 svn_client_merge_peg3(const char *source,
                       const apr_array_header_t *ranges_to_merge,
                       const svn_opt_revision_t *peg_revision,