You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/10/21 04:00:47 UTC

svn commit: r1400556 [17/29] - in /subversion/branches/ev2-export: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/ contrib/client-side/emacs/ contrib/client-side/svn-push/ contrib/client-side/svnmerge/ contrib/hook-...

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/version.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/version.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/version.c Sun Oct 21 02:00:31 2012
@@ -26,7 +26,9 @@
 #include "svn_error.h"
 #include "svn_version.h"
 
+#include "sysinfo.h"
 #include "svn_private_config.h"
+#include "private/svn_subr_private.h"
 
 const svn_version_t *
 svn_subr_version(void)
@@ -96,3 +98,181 @@ svn_ver_check_list(const svn_version_t *
 
   return err;
 }
+
+
+struct svn_version_extended_t
+{
+  const char *build_date;       /* Compilation date */
+  const char *build_time;       /* Compilation time */
+  const char *build_host;       /* Build canonical host name */
+  const char *copyright;        /* Copyright notice (localized) */
+  const char *runtime_host;     /* Runtime canonical host name */
+  const char *runtime_osname;   /* Running OS release name */
+
+  /* Array of svn_version_ext_linked_lib_t describing dependent
+     libraries. */
+  const apr_array_header_t *linked_libs;
+
+  /* Array of svn_version_ext_loaded_lib_t describing loaded shared
+     libraries. */
+  const apr_array_header_t *loaded_libs;
+};
+
+
+const svn_version_extended_t *
+svn_version_extended(svn_boolean_t verbose,
+                     apr_pool_t *pool)
+{
+  svn_version_extended_t *info = apr_pcalloc(pool, sizeof(*info));
+
+  info->build_date = __DATE__;
+  info->build_time = __TIME__;
+  info->build_host = SVN_BUILD_HOST;
+  info->copyright = apr_pstrdup
+    (pool, _("Copyright (C) 2012 The Apache Software Foundation.\n"
+             "This software consists of contributions made by many people;\n"
+             "see the NOTICE file for more information.\n"
+             "Subversion is open source software, see "
+             "http://subversion.apache.org/\n"));
+
+  if (verbose)
+    {
+      info->runtime_host = svn_sysinfo__canonical_host(pool);
+      info->runtime_osname = svn_sysinfo__release_name(pool);
+      info->linked_libs = svn_sysinfo__linked_libs(pool);
+      info->loaded_libs = svn_sysinfo__loaded_libs(pool);
+    }
+
+  return info;
+}
+
+
+const char *
+svn_version_ext_build_date(const svn_version_extended_t *ext_info)
+{
+  return ext_info->build_date;
+}
+
+const char *
+svn_version_ext_build_time(const svn_version_extended_t *ext_info)
+{
+  return ext_info->build_time;
+}
+
+const char *
+svn_version_ext_build_host(const svn_version_extended_t *ext_info)
+{
+  return ext_info->build_host;
+}
+
+const char *
+svn_version_ext_copyright(const svn_version_extended_t *ext_info)
+{
+  return ext_info->copyright;
+}
+
+const char *
+svn_version_ext_runtime_host(const svn_version_extended_t *ext_info)
+{
+  return ext_info->runtime_host;
+}
+
+const char *
+svn_version_ext_runtime_osname(const svn_version_extended_t *ext_info)
+{
+  return ext_info->runtime_osname;
+}
+
+const apr_array_header_t *
+svn_version_ext_linked_libs(const svn_version_extended_t *ext_info)
+{
+  return ext_info->linked_libs;
+}
+
+const apr_array_header_t *
+svn_version_ext_loaded_libs(const svn_version_extended_t *ext_info)
+{
+  return ext_info->loaded_libs;
+}
+
+svn_error_t *
+svn_version__parse_version_string(svn_version_t **version_p,
+                                  const char *version_string,
+                                  apr_pool_t *result_pool)
+{
+  svn_error_t *err;
+  svn_version_t *version;
+  apr_array_header_t *pieces = 
+    svn_cstring_split(version_string, ".", FALSE, result_pool);
+
+  if ((pieces->nelts < 2) || (pieces->nelts > 3))
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, NULL, NULL);
+
+  version = apr_pcalloc(result_pool, sizeof(*version));
+  version->tag = "";
+
+  /* Parse the major and minor integers strictly. */
+  err = svn_cstring_atoi(&(version->major),
+                         APR_ARRAY_IDX(pieces, 0, const char *));
+  if (err)
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+  err = svn_cstring_atoi(&(version->minor),
+                         APR_ARRAY_IDX(pieces, 1, const char *));
+  if (err)
+    return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING, err, NULL);
+
+  /* If there's a third component, we'll parse it, too.  But we don't
+     require that it be present. */
+  if (pieces->nelts == 3)
+    {
+      const char *piece = APR_ARRAY_IDX(pieces, 2, const char *);
+      char *hyphen = strchr(piece, '-');
+      if (hyphen)
+        {
+          version->tag = apr_pstrdup(result_pool, hyphen + 1);
+          *hyphen = '\0';
+        }
+      err = svn_cstring_atoi(&(version->patch), piece);
+      if (err)
+        return svn_error_create(SVN_ERR_MALFORMED_VERSION_STRING,
+                                err, NULL);
+    }
+
+  *version_p = version;
+  return SVN_NO_ERROR;
+}
+
+
+svn_boolean_t
+svn_version__at_least(svn_version_t *version,
+                      int major,
+                      int minor,
+                      int patch)
+{
+  /* Compare major versions. */
+  if (version->major < major)
+    return FALSE;
+  if (version->major > major)
+    return TRUE;
+
+  /* Major versions are the same.  Compare minor versions. */
+  if (version->minor < minor)
+    return FALSE;
+  if (version->minor > minor)
+    return TRUE;
+
+  /* Major and minor versions are the same.  Compare patch
+     versions. */
+  if (version->patch < patch)
+    return FALSE;
+  if (version->patch > patch)
+    return TRUE;
+
+  /* Major, minor, and patch versions are identical matches.  But tags
+     in our schema are always used for versions not yet quite at the
+     given patch level. */
+  if (version->tag && version->tag[0])
+    return FALSE;
+
+  return TRUE;
+}

Modified: subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/win32_crypto.c Sun Oct 21 02:00:31 2012
@@ -145,7 +145,7 @@ windows_password_decrypter(svn_boolean_t
 
   SVN_ERR(svn_auth__simple_password_get(done, &in, creds, realmstring, username,
                                         parameters, non_interactive, pool));
-  if (!done)
+  if (!*done)
     return SVN_NO_ERROR;
 
   orig = svn_base64_decode_string(svn_string_create(in, pool), pool);
@@ -270,7 +270,7 @@ windows_ssl_client_cert_pw_decrypter(svn
   SVN_ERR(svn_auth__ssl_client_cert_pw_get(done, &in, creds, realmstring,
                                            username, parameters,
                                            non_interactive, pool));
-  if (!done)
+  if (!*done)
     return SVN_NO_ERROR;
 
   orig = svn_base64_decode_string(svn_string_create(in, pool), pool);

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_files.c Sun Oct 21 02:00:31 2012
@@ -528,23 +528,22 @@ svn_wc__adm_destroy(svn_wc__db_t *db,
                     void *cancel_baton,
                     apr_pool_t *scratch_pool)
 {
-  const char *adm_abspath;
+  svn_boolean_t is_wcroot;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath));
 
   SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
 
-  SVN_ERR(svn_wc__db_get_wcroot(&adm_abspath, db, dir_abspath,
-                                scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, dir_abspath, scratch_pool));
 
   /* Well, the coast is clear for blowing away the administrative
      directory, which also removes remaining locks */
 
   /* Now close the DB, and we can delete the working copy */
-  if (strcmp(adm_abspath, dir_abspath) == 0)
+  if (is_wcroot)
     {
-      SVN_ERR(svn_wc__db_drop_root(db, adm_abspath, scratch_pool));
-      SVN_ERR(svn_io_remove_dir2(svn_wc__adm_child(adm_abspath, NULL,
+      SVN_ERR(svn_wc__db_drop_root(db, dir_abspath, scratch_pool));
+      SVN_ERR(svn_io_remove_dir2(svn_wc__adm_child(dir_abspath, NULL,
                                                    scratch_pool),
                                  FALSE,
                                  cancel_func, cancel_baton,

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/adm_ops.c Sun Oct 21 02:00:31 2012
@@ -52,6 +52,7 @@
 
 #include "wc.h"
 #include "adm_files.h"
+#include "conflicts.h"
 #include "props.h"
 #include "translate.h"
 #include "workqueue.h"
@@ -108,11 +109,19 @@ svn_wc__get_committed_queue_pool(const s
  *   - queue deletion of the old pristine texts by the remembered checksums.
  *
  * CHECKSUM is the checksum of the new text base for LOCAL_ABSPATH, and must
- * be provided if there is one, else NULL. */
+ * be provided if there is one, else NULL.
+ *
+ * STATUS, KIND, PROP_MODS and OLD_CHECKSUM are the current in-db values of
+ * the node LOCAL_ABSPATH.
+ */
 static svn_error_t *
 process_committed_leaf(svn_wc__db_t *db,
                        const char *local_abspath,
                        svn_boolean_t via_recurse,
+                       svn_wc__db_status_t status,
+                       svn_kind_t kind,
+                       svn_boolean_t prop_mods,
+                       const svn_checksum_t *old_checksum,
                        svn_revnum_t new_revnum,
                        apr_time_t new_changed_date,
                        const char *new_changed_author,
@@ -122,26 +131,11 @@ process_committed_leaf(svn_wc__db_t *db,
                        const svn_checksum_t *checksum,
                        apr_pool_t *scratch_pool)
 {
-  svn_wc__db_status_t status;
-  svn_kind_t kind;
-  const svn_checksum_t *copied_checksum;
   svn_revnum_t new_changed_rev = new_revnum;
-  svn_boolean_t have_base;
-  svn_boolean_t have_work;
-  svn_boolean_t had_props;
-  svn_boolean_t prop_mods;
   svn_skel_t *work_item = NULL;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, &copied_checksum,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, &had_props, &prop_mods,
-                               &have_base, NULL, &have_work,
-                               db, local_abspath,
-                               scratch_pool, scratch_pool));
-
   {
     const char *adm_abspath;
 
@@ -155,11 +149,12 @@ process_committed_leaf(svn_wc__db_t *db,
   if (status == svn_wc__db_status_deleted)
     {
       return svn_error_trace(
-                svn_wc__db_op_remove_node(
+                svn_wc__db_base_remove(
                                 db, local_abspath,
-                                (have_base && !via_recurse)
+                                FALSE /* keep_as_working */,
+                                (! via_recurse)
                                     ? new_revnum : SVN_INVALID_REVNUM,
-                                kind,
+                                NULL, NULL,
                                 scratch_pool));
     }
   else if (status == svn_wc__db_status_not_present)
@@ -186,9 +181,9 @@ process_committed_leaf(svn_wc__db_t *db,
         {
           /* It was copied and not modified. We must have a text
              base for it. And the node should have a checksum. */
-          SVN_ERR_ASSERT(copied_checksum != NULL);
+          SVN_ERR_ASSERT(old_checksum != NULL);
 
-          checksum = copied_checksum;
+          checksum = old_checksum;
 
           /* Is the node completely unmodified and are we recursing? */
           if (via_recurse && !prop_mods)
@@ -250,26 +245,41 @@ svn_wc__process_committed_internal(svn_w
                                    const svn_wc_committed_queue_t *queue,
                                    apr_pool_t *scratch_pool)
 {
+  svn_wc__db_status_t status;
   svn_kind_t kind;
+  const svn_checksum_t *old_checksum;
+  svn_boolean_t prop_mods;
+
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, &old_checksum, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, &prop_mods, NULL, NULL, NULL,
+                               db, local_abspath,
+                               scratch_pool, scratch_pool));
 
   /* NOTE: be wary of making crazy semantic changes in this function, since
      svn_wc_process_committed4() calls this.  */
 
   SVN_ERR(process_committed_leaf(db, local_abspath, !top_of_recurse,
+                                 status, kind, prop_mods, old_checksum,
                                  new_revnum, new_date, rev_author,
                                  new_dav_cache,
                                  no_unlock, keep_changelist,
                                  sha1_checksum,
                                  scratch_pool));
 
-  /* Only check kind after processing the node itself. The node might
-     have been deleted */
-  SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath,
-                               TRUE /* allow_missing */,
-                               TRUE /* show_hidden */,
-                               scratch_pool));
+  /* Only check for recursion on nodes that have children */
+  if (kind != svn_kind_file
+      || status == svn_wc__db_status_not_present
+      || status == svn_wc__db_status_excluded
+      || status == svn_wc__db_status_server_excluded
+      /* Node deleted -> then no longer a directory */
+      || status == svn_wc__db_status_deleted)
+    {
+      return SVN_NO_ERROR;
+    }
 
-  if (recurse && kind == svn_kind_dir)
+  if (recurse)
     {
       const apr_array_header_t *children;
       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
@@ -284,38 +294,17 @@ svn_wc__process_committed_internal(svn_w
         {
           const char *name = APR_ARRAY_IDX(children, i, const char *);
           const char *this_abspath;
-          svn_wc__db_status_t status;
+          const committed_queue_item_t *cqi;
 
           svn_pool_clear(iterpool);
 
           this_abspath = svn_dirent_join(local_abspath, name, iterpool);
 
-          SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       db, this_abspath,
-                                       iterpool, iterpool));
-
-          /* We come to this branch since we have committed a copied tree.
-             svn_depth_exclude is possible in this situation. So check and
-             skip */
-          if (status == svn_wc__db_status_excluded)
-            continue;
-
           sha1_checksum = NULL;
-          if (kind != svn_kind_dir && queue != NULL)
-            {
-              const committed_queue_item_t *cqi;
+          cqi = apr_hash_get(queue->queue, this_abspath, APR_HASH_KEY_STRING);
 
-              cqi = apr_hash_get(queue->queue, this_abspath,
-                                 APR_HASH_KEY_STRING);
-              if (cqi != NULL)
-                {
-                  sha1_checksum = cqi->sha1_checksum;
-                }
-            }
+          if (cqi != NULL)
+            sha1_checksum = cqi->sha1_checksum;
 
           /* Recurse.  Pass NULL for NEW_DAV_CACHE, because the
              ones present in the current call are only applicable to
@@ -598,6 +587,72 @@ erase_unversioned_from_wc(const char *pa
   return SVN_NO_ERROR;
 }
 
+/* Helper for svn_wc__delete and svn_wc__delete_many */
+static svn_error_t *
+create_delete_wq_items(svn_skel_t **work_items,
+                       svn_wc__db_t *db,
+                       const char *local_abspath,
+                       svn_kind_t kind,
+                       svn_boolean_t conflicted,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  *work_items = NULL;
+
+  /* Schedule the on-disk delete */
+  if (kind == svn_kind_dir)
+    SVN_ERR(svn_wc__wq_build_dir_remove(work_items, db, local_abspath,
+                                        local_abspath,
+                                        TRUE /* recursive */,
+                                        result_pool, scratch_pool));
+  else
+    SVN_ERR(svn_wc__wq_build_file_remove(work_items, db, local_abspath,
+                                         local_abspath,
+                                         result_pool, scratch_pool));
+
+  /* Read conflicts, to allow deleting the markers after updating the DB */
+  if (conflicted)
+    {
+      svn_skel_t *conflict;
+      const apr_array_header_t *markers;
+      int i;
+
+      SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath,
+                                       scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_read_markers(&markers, db, local_abspath,
+                                            conflict,
+                                            scratch_pool, scratch_pool));
+
+      /* Maximum number of markers is 4, so no iterpool */
+      for (i = 0; markers && i < markers->nelts; i++)
+        {
+          const char *marker_abspath;
+          svn_node_kind_t marker_kind;
+
+          marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
+          SVN_ERR(svn_io_check_path(marker_abspath, &marker_kind,
+                                    scratch_pool));
+
+          if (marker_kind == svn_node_file)
+            {
+              svn_skel_t *work_item;
+
+              SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
+                                                   marker_abspath,
+                                                   result_pool,
+                                                   scratch_pool));
+
+              *work_items = svn_wc__wq_merge(*work_items, work_item,
+                                             result_pool);
+            }
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__delete_many(svn_wc_context_t *wc_ctx,
                     const apr_array_header_t *targets,
@@ -613,7 +668,7 @@ svn_wc__delete_many(svn_wc_context_t *wc
   svn_error_t *err;
   svn_wc__db_status_t status;
   svn_kind_t kind;
-  const apr_array_header_t *conflicts = NULL;
+  svn_skel_t *work_items = NULL;
   apr_array_header_t *versioned_targets;
   const char *local_abspath;
   int i;
@@ -689,74 +744,39 @@ svn_wc__delete_many(svn_wc_context_t *wc
                                                          iterpool),
                                   iterpool));
 
-      /* Read conflicts, to allow deleting the markers after updating the DB */
-      if (!keep_local && conflicted)
-        SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath,
-                                       scratch_pool, iterpool));
+      /* Prepare the on-disk delete */
+      if (!keep_local)
+        {
+          svn_skel_t *work_item;
+
+          SVN_ERR(create_delete_wq_items(&work_item, db, local_abspath, kind,
+                                         conflicted,
+                                         scratch_pool, iterpool));
 
+          work_items = svn_wc__wq_merge(work_items, work_item,
+                                        scratch_pool);
+        }
     }
 
   if (versioned_targets->nelts == 0)
     return SVN_NO_ERROR;
 
   SVN_ERR(svn_wc__db_op_delete_many(db, versioned_targets,
+                                    !keep_local /* delete_dir_externals */,
+                                    work_items,
                                     cancel_func, cancel_baton,
-                                    notify_func, notify_baton, scratch_pool));
+                                    notify_func, notify_baton,
+                                    iterpool));
 
-  if (!keep_local && conflicts != NULL)
+  if (work_items != NULL)
     {
-      svn_pool_clear(iterpool);
-
-      /* Do we have conflict markers that should be removed? */
-      for (i = 0; i < conflicts->nelts; i++)
-        {
-          const svn_wc_conflict_description2_t *desc;
-
-          desc = APR_ARRAY_IDX(conflicts, i,
-                               const svn_wc_conflict_description2_t*);
+      /* Our only caller locked the wc, so for now assume it only passed
+         nodes from a single wc (asserted in svn_wc__db_op_delete_many) */
+      local_abspath = APR_ARRAY_IDX(versioned_targets, 0, const char *);
 
-          if (desc->kind == svn_wc_conflict_kind_text)
-            {
-              if (desc->base_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
-                                              iterpool));
-                }
-              if (desc->their_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                              iterpool));
-                }
-              if (desc->my_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
-                                              iterpool));
-                }
-            }
-          else if (desc->kind == svn_wc_conflict_kind_property
-                   && desc->their_abspath != NULL)
-            {
-              SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                          iterpool));
-            }
-        }
-    }
-
-  /* By the time we get here, the db knows that all targets are now
-   * unversioned. */
-  if (!keep_local)
-    {
-      for (i = 0; i < versioned_targets->nelts; i++)
-        {
-          svn_pool_clear(iterpool);
-
-          local_abspath = APR_ARRAY_IDX(versioned_targets, i, const char *);
-          SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
-                                            cancel_func, cancel_baton,
-                                            iterpool));
-        }
+      SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                             iterpool));
     }
-
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
@@ -780,7 +800,7 @@ svn_wc__delete_internal(svn_wc_context_t
   svn_wc__db_status_t status;
   svn_kind_t kind;
   svn_boolean_t conflicted;
-  const apr_array_header_t *conflicts;
+  svn_skel_t *work_items = NULL;
 
   err = svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
                              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -834,64 +854,24 @@ svn_wc__delete_internal(svn_wc_context_t
   SVN_ERR(svn_wc__write_check(db, svn_dirent_dirname(local_abspath, pool),
                               pool));
 
-  /* Read conflicts, to allow deleting the markers after updating the DB */
-  if (!keep_local && conflicted)
-    SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath,
-                                   scratch_pool, scratch_pool));
+  /* Prepare the on-disk delete */
+      if (!keep_local)
+        {
+          SVN_ERR(create_delete_wq_items(&work_items, db, local_abspath, kind,
+                                         conflicted,
+                                         scratch_pool, scratch_pool));
+        }
 
   SVN_ERR(svn_wc__db_op_delete(db, local_abspath, moved_to_abspath,
-                               NULL, NULL,
+                               !keep_local /* delete_dir_externals */,
+                               NULL, work_items,
                                cancel_func, cancel_baton,
                                notify_func, notify_baton,
                                pool));
 
-  if (!keep_local && conflicted && conflicts != NULL)
-    {
-      int i;
-
-      /* Do we have conflict markers that should be removed? */
-      for (i = 0; i < conflicts->nelts; i++)
-        {
-          const svn_wc_conflict_description2_t *desc;
-
-          desc = APR_ARRAY_IDX(conflicts, i,
-                               const svn_wc_conflict_description2_t*);
-
-          if (desc->kind == svn_wc_conflict_kind_text)
-            {
-              if (desc->base_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->base_abspath, TRUE,
-                                              scratch_pool));
-                }
-              if (desc->their_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                              scratch_pool));
-                }
-              if (desc->my_abspath != NULL)
-                {
-                  SVN_ERR(svn_io_remove_file2(desc->my_abspath, TRUE,
-                                              scratch_pool));
-                }
-            }
-          else if (desc->kind == svn_wc_conflict_kind_property
-                   && desc->their_abspath != NULL)
-            {
-              SVN_ERR(svn_io_remove_file2(desc->their_abspath, TRUE,
-                                          scratch_pool));
-            }
-        }
-    }
-
-  /* By the time we get here, the db knows that everything that is still at
-     LOCAL_ABSPATH is unversioned. */
-  if (!keep_local)
-    {
-        SVN_ERR(erase_unversioned_from_wc(local_abspath, TRUE,
-                                          cancel_func, cancel_baton,
-                                          pool));
-    }
+  if (work_items)
+    SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton,
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1039,6 +1019,7 @@ check_can_add_node(svn_node_kind_t *kind
   const char *base_name = svn_dirent_basename(local_abspath, scratch_pool);
   svn_boolean_t is_wc_root;
   svn_node_kind_t kind;
+  svn_boolean_t is_special;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(!copyfrom_url || (svn_uri_is_canonical(copyfrom_url,
@@ -1055,7 +1036,8 @@ check_can_add_node(svn_node_kind_t *kind
   SVN_ERR(svn_path_check_valid(local_abspath, scratch_pool));
 
   /* Make sure something's there; set KIND and *KIND_P. */
-  SVN_ERR(svn_io_check_path(local_abspath, &kind, scratch_pool));
+  SVN_ERR(svn_io_check_special_path(local_abspath, &kind, &is_special,
+                                    scratch_pool));
   if (kind == svn_node_none)
     return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
                              _("'%s' not found"),
@@ -1117,14 +1099,20 @@ check_can_add_node(svn_node_kind_t *kind
               SVN_ERR_ASSERT(!is_wc_root);
               break;
             case svn_wc__db_status_normal:
-              if (copyfrom_url)
-                {
-                  SVN_ERR(svn_wc__check_wc_root(&is_wc_root, NULL, NULL,
-                                                db, local_abspath,
-                                                scratch_pool));
+              SVN_ERR(svn_wc__db_is_wcroot(&is_wc_root, db, local_abspath,
+                                           scratch_pool));
 
-                  if (is_wc_root)
-                    break;
+              if (is_wc_root && copyfrom_url)
+                {
+                  /* Integrate a sub working copy in a parent working copy
+                     (legacy behavior) */
+                  break;
+                }
+              else if (is_wc_root && is_special)
+                {
+                  /* Adding a symlink to a working copy root.
+                     (special_tests.py 23: externals as symlink targets) */
+                  break;
                 }
               /* else: Fall through in default error */
 
@@ -1972,12 +1960,14 @@ revert_internal(svn_wc__db_t *db,
      when local_abspath is the working copy root. */
   {
     const char *dir_abspath;
+    svn_boolean_t is_wcroot;
 
-    SVN_ERR(svn_wc__db_get_wcroot(&dir_abspath, db, local_abspath,
-                                  scratch_pool, scratch_pool));
+    SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, local_abspath, scratch_pool));
 
-    if (svn_dirent_is_child(dir_abspath, local_abspath, NULL))
+    if (! is_wcroot)
       dir_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+    else
+      dir_abspath = local_abspath;
 
     SVN_ERR(svn_wc__write_check(db, dir_abspath, scratch_pool));
   }
@@ -2127,7 +2117,7 @@ revert_partial(svn_wc__db_t *db,
         {
           svn_kind_t kind;
 
-          SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath,
+          SVN_ERR(svn_wc__db_read_kind(&kind, db, child_abspath,
                                        FALSE /* allow_missing */,
                                        FALSE /* show_hidden */,
                                        iterpool));
@@ -2330,214 +2320,68 @@ svn_error_t *
 svn_wc__internal_remove_from_revision_control(svn_wc__db_t *db,
                                               const char *local_abspath,
                                               svn_boolean_t destroy_wf,
-                                              svn_boolean_t instant_error,
                                               svn_cancel_func_t cancel_func,
                                               void *cancel_baton,
                                               apr_pool_t *scratch_pool)
 {
-  svn_error_t *err;
   svn_boolean_t left_something = FALSE;
-  svn_wc__db_status_t status;
-  svn_kind_t kind;
+  svn_boolean_t is_root;
+  svn_error_t *err = NULL;
 
-  /* ### This whole function should be rewritten to run inside a transaction,
-     ### to allow a stable cancel behavior.
-     ###
-     ### Subversion < 1.7 marked the directory as incomplete to allow updating
-     ### it from a canceled state. But this would not work because update
-     ### doesn't retrieve deleted items.
-     ###
-     ### WC-NG doesn't support a delete+incomplete state, but we can't build
-     ### transactions over multiple databases yet. */
+  SVN_ERR(svn_wc__db_is_wcroot(&is_root, db, local_abspath, scratch_pool));
 
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  /* Check cancellation here, so recursive calls get checked early. */
-  if (cancel_func)
-    SVN_ERR(cancel_func(cancel_baton));
-
-  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL,
-                               db, local_abspath, scratch_pool, scratch_pool));
-
-  if (kind == svn_kind_file || kind == svn_kind_symlink)
-    {
-      svn_boolean_t text_modified_p = FALSE;
-
-      if (instant_error || destroy_wf)
-        {
-          svn_node_kind_t on_disk;
-          SVN_ERR(svn_io_check_path(local_abspath, &on_disk, scratch_pool));
-          if (on_disk == svn_node_file)
-            {
-              /* Check for local mods. before removing entry */
-              SVN_ERR(svn_wc__internal_file_modified_p(&text_modified_p, db,
-                                                       local_abspath, FALSE,
-                                                       scratch_pool));
-              if (text_modified_p && instant_error)
-                return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
-                       _("File '%s' has local modifications"),
-                       svn_dirent_local_style(local_abspath, scratch_pool));
-            }
-        }
+  SVN_ERR(svn_wc__db_op_remove_node(&left_something,
+                                    db, local_abspath,
+                                    destroy_wf /* destroy_wc */,
+                                    destroy_wf /* destroy_changes */,
+                                    SVN_INVALID_REVNUM,
+                                    svn_wc__db_status_not_present,
+                                    svn_kind_none,
+                                    NULL, NULL,
+                                    cancel_func, cancel_baton,
+                                    scratch_pool));
 
-      /* Remove NAME from DB */
-      SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
-                                        SVN_INVALID_REVNUM,
-                                        svn_kind_unknown,
-                                        scratch_pool));
-
-      /* If we were asked to destroy the working file, do so unless
-         it has local mods. */
-      if (destroy_wf)
-        {
-          /* Don't kill local mods. */
-          if (text_modified_p)
-            return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
-          else  /* The working file is still present; remove it. */
-            SVN_ERR(svn_io_remove_file2(local_abspath, TRUE, scratch_pool));
-        }
+  SVN_ERR(svn_wc__wq_run(db, local_abspath,
+                         cancel_func, cancel_baton,
+                         scratch_pool));
 
-    }  /* done with file case */
-  else /* looking at THIS_DIR */
+  if (is_root)
     {
-      apr_pool_t *iterpool = svn_pool_create(scratch_pool);
-      const apr_array_header_t *children;
-      int i;
-
-      /* ### sanity check:  check 2 places for DELETED flag? */
-
-      /* Walk over every entry. */
-      SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath,
-                                       scratch_pool, iterpool));
-
-      for (i = 0; i < children->nelts; i++)
-        {
-          const char *node_name = APR_ARRAY_IDX(children, i, const char*);
-          const char *node_abspath;
-          svn_wc__db_status_t node_status;
-          svn_kind_t node_kind;
-
-          svn_pool_clear(iterpool);
-
-          node_abspath = svn_dirent_join(local_abspath, node_name, iterpool);
-
-          SVN_ERR(svn_wc__db_read_info(&node_status, &node_kind, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL, NULL,
-                                       NULL, NULL, NULL, NULL, NULL,
-                                       db, node_abspath,
-                                       iterpool, iterpool));
-
-          if (node_status == svn_wc__db_status_normal
-              && node_kind == svn_kind_dir)
-            {
-              svn_boolean_t is_root;
-
-              SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
-                                            db, node_abspath, iterpool));
-
-              if (is_root)
-                continue; /* Just skip working copies as obstruction */
-            }
-
-          if (node_status != svn_wc__db_status_normal
-              && node_status != svn_wc__db_status_added
-              && node_status != svn_wc__db_status_incomplete)
-            {
-              /* The node is already 'deleted', so nothing to do on
-                 versioned nodes */
-              SVN_ERR(svn_wc__db_op_remove_node(db, node_abspath,
-                                                SVN_INVALID_REVNUM,
-                                                svn_kind_unknown,
-                                                iterpool));
-
-              continue;
-            }
-
-          err = svn_wc__internal_remove_from_revision_control(
-                            db, node_abspath,
-                            destroy_wf, instant_error,
-                            cancel_func, cancel_baton,
-                            iterpool);
-
-          if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
-            {
-              if (instant_error)
-                return svn_error_trace(err);
-              else
-                {
-                  svn_error_clear(err);
-                  left_something = TRUE;
-                }
-            }
-          else if (err)
-            return svn_error_trace(err);
-        }
-
-      /* At this point, every directory below this one has been
-         removed from revision control. */
-
-      /* Remove self from parent's entries file, but only if parent is
-         a working copy.  If it's not, that's fine, we just move on. */
-      {
-        svn_boolean_t is_root;
-
-        SVN_ERR(svn_wc__check_wc_root(&is_root, NULL, NULL,
-                                      db, local_abspath, iterpool));
-
-        /* If full_path is not the top of a wc, then its parent
-           directory is also a working copy and has an entry for
-           full_path.  We need to remove that entry: */
-        if (! is_root)
-          {
-            SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
-                                              SVN_INVALID_REVNUM,
-                                              svn_kind_unknown,
-                                              iterpool));
-          }
-        else
-          {
-            /* Remove the entire administrative .svn area, thereby removing
-               _this_ dir from revision control too.  */
-            SVN_ERR(svn_wc__adm_destroy(db, local_abspath,
-                                        cancel_func, cancel_baton, iterpool));
-          }
-      }
-
-      /* If caller wants us to recursively nuke everything on disk, go
-         ahead, provided that there are no dangling local-mod files
-         below */
-      if (destroy_wf && (! left_something))
-        {
-          /* If the dir is *truly* empty (i.e. has no unversioned
-             resources, all versioned files are gone, all .svn dirs are
-             gone, and contains nothing but empty dirs), then a
-             *non*-recursive dir_remove should work.  If it doesn't,
-             no big deal.  Just assume there are unversioned items in
-             there and set "left_something" */
-          err = svn_io_dir_remove_nonrecursive(local_abspath, iterpool);
-          if (err)
-            {
-              if (!APR_STATUS_IS_ENOENT(err->apr_err))
-                left_something = TRUE;
-              svn_error_clear(err);
-            }
-        }
-
-      svn_pool_destroy(iterpool);
+      /* Destroy the administrative area */
+      SVN_ERR(svn_wc__adm_destroy(db, local_abspath, cancel_func, cancel_baton,
+                                  scratch_pool));
 
-    }  /* end of directory case */
+      /* And if we didn't leave something interesting, remove the directory */
+      if (!left_something && destroy_wf)
+        err = svn_io_dir_remove_nonrecursive(local_abspath, scratch_pool);
+    }
 
-  if (left_something)
-    return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL, NULL);
+  if (left_something || err)
+    return svn_error_create(SVN_ERR_WC_LEFT_LOCAL_MOD, err, NULL);
 
   return SVN_NO_ERROR;
 }
 
+/* Implements svn_wc_status_func4_t for svn_wc_remove_from_revision_control2 */
+static svn_error_t *
+remove_from_revision_status_callback(void *baton,
+                                     const char *local_abspath,
+                                     const svn_wc_status3_t *status,
+                                     apr_pool_t *scratch_pool)
+{
+  /* For legacy reasons we only check the file contents for changes */
+  if (status->versioned
+      && status->kind == svn_node_file
+      && (status->text_status == svn_wc_status_modified
+          || status->text_status == svn_wc_status_conflicted))
+    {
+      return svn_error_createf(SVN_ERR_WC_LEFT_LOCAL_MOD, NULL,
+                               _("File '%s' has local modifications"),
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_wc_remove_from_revision_control2(svn_wc_context_t *wc_ctx,
@@ -2548,11 +2392,18 @@ svn_wc_remove_from_revision_control2(svn
                                     void *cancel_baton,
                                     apr_pool_t *scratch_pool)
 {
+  if (instant_error)
+    {
+      SVN_ERR(svn_wc_walk_status(wc_ctx, local_abspath, svn_depth_infinity,
+                                 FALSE, FALSE, FALSE, NULL,
+                                 remove_from_revision_status_callback, NULL,
+                                 cancel_func, cancel_baton,
+                                 scratch_pool));
+    }
   return svn_error_trace(
       svn_wc__internal_remove_from_revision_control(wc_ctx->db,
                                                     local_abspath,
                                                     destroy_wf,
-                                                    instant_error,
                                                     cancel_func,
                                                     cancel_baton,
                                                     scratch_pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/cleanup.c Sun Oct 21 02:00:31 2012
@@ -142,7 +142,7 @@ cleanup_internal(svn_wc__db_t *db,
                  apr_pool_t *scratch_pool)
 {
   int wc_format;
-  const char *cleanup_abspath;
+  svn_boolean_t is_wcroot;
 
   /* Can we even work with this directory?  */
   SVN_ERR(can_be_cleaned(&wc_format, db, dir_abspath, scratch_pool));
@@ -157,8 +157,7 @@ cleanup_internal(svn_wc__db_t *db,
     SVN_ERR(svn_wc__wq_run(db, dir_abspath, cancel_func, cancel_baton,
                            scratch_pool));
 
-  SVN_ERR(svn_wc__db_get_wcroot(&cleanup_abspath, db, dir_abspath,
-                                scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_is_wcroot(&is_wcroot, db, dir_abspath, scratch_pool));
 
 #ifdef SVN_DEBUG
   SVN_ERR(svn_wc__db_verify(db, dir_abspath, scratch_pool));
@@ -169,7 +168,7 @@ cleanup_internal(svn_wc__db_t *db,
      svn_wc__check_wcroot() as that function, will just return true
      once we start sharing databases with externals.
    */
-  if (strcmp(cleanup_abspath, dir_abspath) == 0)
+  if (is_wcroot)
     {
     /* Cleanup the tmp area of the admin subdir, if running the log has not
        removed it!  The logs have been run, so anything left here has no hope

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.c Sun Oct 21 02:00:31 2012
@@ -511,9 +511,6 @@ static const svn_token_map_t local_chang
   { "replaced",         svn_wc_conflict_reason_replaced },
   { "moved-away",       svn_wc_conflict_reason_moved_away },
   { "moved-here",       svn_wc_conflict_reason_moved_here },
-  /* ### Do we really need this. The edit state is on a different node,
-         which might just change while the tree conflict exists? */
-  { "moved-and-edited", svn_wc_conflict_reason_moved_away_and_edited },
   { NULL }
 };
 
@@ -1155,7 +1152,7 @@ svn_wc__conflict_create_markers(svn_skel
           SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath,
                                                  scratch_pool, scratch_pool));
         else
-          old_props = their_props;
+          old_props = their_original_props;
 
         prop_data = prop_conflict_skel_new(result_pool);
 
@@ -1165,7 +1162,7 @@ svn_wc__conflict_create_markers(svn_skel
           {
             const char *propname = svn__apr_hash_index_key(hi);
 
-            prop_conflict_skel_add(
+            SVN_ERR(prop_conflict_skel_add(
                             prop_data, propname,
                             old_props
                                     ? apr_hash_get(old_props, propname,
@@ -1183,7 +1180,7 @@ svn_wc__conflict_create_markers(svn_skel
                                     ? apr_hash_get(their_original_props, propname,
                                                    APR_HASH_KEY_STRING)
                                       : NULL,
-                            result_pool, scratch_pool);
+                            result_pool, scratch_pool));
           }
 
         SVN_ERR(svn_wc__wq_build_prej_install(work_items,
@@ -1603,11 +1600,15 @@ eval_text_conflict_func_result(svn_skel_
                                           FALSE /* record_fileinfo */,
                                           result_pool, scratch_pool));
     *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+    
+    SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db, local_abspath,
+                                             result_pool, scratch_pool));
+    *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
 
     if (remove_source)
       {
         SVN_ERR(svn_wc__wq_build_file_remove(&work_item,
-                                             db, install_from,
+                                             db, local_abspath, install_from,
                                              result_pool, scratch_pool));
         *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
       }
@@ -1682,7 +1683,6 @@ save_merge_result(svn_skel_t **work_item
                                                 db, local_abspath,
                                                 source, edited_copy_abspath,
                                                 result_pool, scratch_pool));
-
   return SVN_NO_ERROR;
 }
 
@@ -1828,7 +1828,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_
         SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath,
                                                scratch_pool, scratch_pool));
       else
-        old_props = their_props;
+        old_props = old_their_props;
 
       iterpool = svn_pool_create(scratch_pool);
 
@@ -1910,10 +1910,164 @@ svn_wc__conflict_invoke_resolver(svn_wc_
   return SVN_NO_ERROR;
 }
 
+/* Read all property conflicts contained in CONFLICT_SKEL into
+ * individual conflict descriptions, and append those descriptions
+ * to the CONFLICTS array.
+ *
+ * If NOT create_tempfiles, always create a legacy property conflict
+ * descriptor.
+ *
+ * Allocate results in RESULT_POOL. SCRATCH_POOL is used for temporary
+ * allocations. */
+static svn_error_t *
+read_prop_conflicts(apr_array_header_t *conflicts,
+                    svn_wc__db_t *db,
+                    const char *local_abspath,
+                    svn_skel_t *conflict_skel,
+                    svn_boolean_t create_tempfiles,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
+{
+  const char *prop_reject_file;
+  apr_hash_t *my_props;
+  apr_hash_t *their_old_props;
+  apr_hash_t *their_props;
+  apr_hash_t *conflicted_props;
+  apr_hash_index_t *hi;
+  apr_pool_t *iterpool;
+  
+  SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file,
+                                              &my_props,
+                                              &their_old_props,
+                                              &their_props,
+                                              &conflicted_props,
+                                              db, local_abspath,
+                                              conflict_skel,
+                                              scratch_pool, scratch_pool));
+
+  if ((! create_tempfiles) || apr_hash_count(conflicted_props) == 0)
+    {
+      /* Legacy prop conflict with only a .reject file. */
+      svn_wc_conflict_description2_t *desc;
+
+      desc  = svn_wc_conflict_description_create_prop2(local_abspath,
+                                                       svn_node_unknown,
+                                                       "", result_pool);
+
+      /* ### This should be changed. The prej file should be stored
+       * ### separately from the other files. We need to rev the
+       * ### conflict description struct for this. */
+      desc->their_abspath = apr_pstrdup(result_pool, prop_reject_file);
+
+      APR_ARRAY_PUSH(conflicts, svn_wc_conflict_description2_t*) = desc;
+
+      return SVN_NO_ERROR;
+    }
+
+  iterpool = svn_pool_create(scratch_pool);
+  for (hi = apr_hash_first(scratch_pool, conflicted_props);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *propname = svn__apr_hash_index_key(hi);
+      svn_string_t *old_value;
+      svn_string_t *my_value;
+      svn_string_t *their_value;
+      svn_wc_conflict_description2_t *desc;
+
+      svn_pool_clear(iterpool);
+
+      desc  = svn_wc_conflict_description_create_prop2(local_abspath,
+                                                       svn_node_unknown,
+                                                       propname,
+                                                       result_pool);
+
+      desc->property_name = apr_pstrdup(result_pool, propname);
+
+      my_value = apr_hash_get(my_props, propname, APR_HASH_KEY_STRING);
+      their_value = apr_hash_get(their_props, propname,
+                                 APR_HASH_KEY_STRING);
+
+      /* Compute the incoming side of the conflict ('action'). */
+      if (their_value == NULL)
+        desc->action = svn_wc_conflict_action_delete;
+      else if (my_value == NULL)
+        desc->action = svn_wc_conflict_action_add;
+      else
+        desc->action = svn_wc_conflict_action_edit;
+
+      /* Compute the local side of the conflict ('reason'). */
+      if (my_value == NULL)
+        desc->reason = svn_wc_conflict_reason_deleted;
+      else if (their_value == NULL)
+        desc->reason = svn_wc_conflict_reason_added;
+      else
+        desc->reason = svn_wc_conflict_reason_edited;
+
+      /* ### This should be changed. The prej file should be stored
+       * ### separately from the other files. We need to rev the
+       * ### conflict description struct for this. */
+      desc->their_abspath = apr_pstrdup(result_pool, prop_reject_file);
+
+      /* ### This should be changed. The conflict description for
+       * ### props should contain these values as svn_string_t,
+       * ### rather than in temporary files. We need to rev the
+       * ### conflict description struct for this. */
+      if (my_value)
+        {
+          svn_stream_t *s;
+          apr_size_t len;
+
+          SVN_ERR(svn_stream_open_unique(&s, &desc->my_abspath, NULL,
+                                         svn_io_file_del_on_pool_cleanup,
+                                         result_pool, iterpool));
+          len = my_value->len;
+          SVN_ERR(svn_stream_write(s, my_value->data, &len));
+          SVN_ERR(svn_stream_close(s));
+        }
+
+      if (their_value)
+        {
+          svn_stream_t *s;
+          apr_size_t len;
+
+          /* ### Currently, their_abspath is used for the prop reject file.
+           * ### Put their value into merged instead...
+           * ### We need to rev the conflict description struct to fix this. */
+          SVN_ERR(svn_stream_open_unique(&s, &desc->merged_file, NULL,
+                                         svn_io_file_del_on_pool_cleanup,
+                                         result_pool, iterpool));
+          len = their_value->len;
+          SVN_ERR(svn_stream_write(s, their_value->data, &len));
+          SVN_ERR(svn_stream_close(s));
+        }
+
+      old_value = apr_hash_get(their_old_props, propname, APR_HASH_KEY_STRING);
+      if (old_value)
+        {
+          svn_stream_t *s;
+          apr_size_t len;
+
+          SVN_ERR(svn_stream_open_unique(&s, &desc->base_abspath, NULL,
+                                         svn_io_file_del_on_pool_cleanup,
+                                         result_pool, iterpool));
+          len = old_value->len;
+          SVN_ERR(svn_stream_write(s, old_value->data, &len));
+          SVN_ERR(svn_stream_close(s));
+        }
+
+      APR_ARRAY_PUSH(conflicts, svn_wc_conflict_description2_t*) = desc;
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_wc__read_conflicts(const apr_array_header_t **conflicts,
                        svn_wc__db_t *db,
                        const char *local_abspath,
+                       svn_boolean_t create_tempfiles,
                        apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool)
 {
@@ -1945,21 +2099,9 @@ svn_wc__read_conflicts(const apr_array_h
                           sizeof(svn_wc_conflict_description2_t*));
 
   if (prop_conflicted)
-    {
-      svn_wc_conflict_description2_t *desc;
-      desc  = svn_wc_conflict_description_create_prop2(local_abspath,
-                                                       svn_node_unknown,
-                                                       "",
-                                                       result_pool);
-
-      SVN_ERR(svn_wc__conflict_read_prop_conflict(&desc->their_abspath,
-                                                  NULL, NULL,  NULL, NULL,
-                                                  db, local_abspath,
-                                                  conflict_skel,
-                                                  result_pool, scratch_pool));
-
-      APR_ARRAY_PUSH(cflcts, svn_wc_conflict_description2_t*) = desc;
-    }
+    SVN_ERR(read_prop_conflicts(cflcts, db, local_abspath, conflict_skel,
+                                create_tempfiles,
+                                result_pool, scratch_pool));
 
   if (text_conflicted)
     {
@@ -2084,10 +2226,9 @@ svn_wc__read_conflicts(const apr_array_h
    and clearing the conflict filenames from the entry.  The latter needs to
    be done whether or not the conflict files exist.
 
-   PATH is the path to the item to be resolved, BASE_NAME is the basename
-   of PATH, and CONFLICT_DIR is the access baton for PATH.  ORIG_ENTRY is
-   the entry prior to resolution. RESOLVE_TEXT and RESOLVE_PROPS are TRUE
-   if text and property conflicts respectively are to be resolved.
+   LOCAL_ABSPATH in DB is the path to the item to be resolved.
+   RESOLVE_TEXT, RESOLVE_PROPS and RESOLVE_TREE are TRUE iff text, property
+   and tree conflicts respectively are to be resolved.
 
    If this call marks any conflict as resolved, set *DID_RESOLVE to true,
    else do not change *DID_RESOLVE.
@@ -2102,15 +2243,16 @@ resolve_conflict_on_node(svn_boolean_t *
                          svn_boolean_t resolve_props,
                          svn_boolean_t resolve_tree,
                          svn_wc_conflict_choice_t conflict_choice,
+                         svn_skel_t *work_items,
                          svn_cancel_func_t cancel_func_t,
                          void *cancel_baton,
                          apr_pool_t *scratch_pool)
 {
   svn_skel_t *conflicts;
+  svn_wc_operation_t operation;
   svn_boolean_t text_conflicted;
   svn_boolean_t prop_conflicted;
   svn_boolean_t tree_conflicted;
-  svn_skel_t *work_items = NULL;
   svn_skel_t *work_item;
   apr_pool_t *pool = scratch_pool;
 
@@ -2122,7 +2264,7 @@ resolve_conflict_on_node(svn_boolean_t *
   if (!conflicts)
     return SVN_NO_ERROR;
 
-  SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, &text_conflicted,
+  SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, &text_conflicted,
                                      &prop_conflicted, &tree_conflicted,
                                      db, local_abspath, conflicts,
                                      scratch_pool, scratch_pool));
@@ -2210,6 +2352,11 @@ resolve_conflict_on_node(svn_boolean_t *
                     &work_item, db, local_abspath,
                     auto_resolve_src, local_abspath, pool, pool));
           work_items = svn_wc__wq_merge(work_items, work_item, pool);
+
+          SVN_ERR(svn_wc__wq_build_sync_file_flags(&work_item, db,
+                                                   local_abspath,
+                                                   pool, pool));
+          work_items = svn_wc__wq_merge(work_items, work_item, pool);
         }
 
       /* Legacy behavior: Only report text conflicts as resolved when at least
@@ -2224,6 +2371,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    conflict_old,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2237,6 +2385,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    conflict_new,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2250,6 +2399,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    conflict_working,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2262,12 +2412,83 @@ resolve_conflict_on_node(svn_boolean_t *
     {
       svn_node_kind_t node_kind;
       const char *prop_reject_file;
+      apr_hash_t *mine_props;
+      apr_hash_t *their_old_props;
+      apr_hash_t *their_props;
+      apr_hash_t *conflicted_props;
+      apr_hash_t *old_props;
+      apr_hash_t *resolve_from = NULL;
 
       SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file,
-                                                  NULL, NULL, NULL, NULL,
+                                                  &mine_props, &their_old_props,
+                                                  &their_props, &conflicted_props,
                                                   db, local_abspath, conflicts,
                                                   scratch_pool, scratch_pool));
 
+      if (operation == svn_wc_operation_merge)
+          SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath,
+                                                 scratch_pool, scratch_pool));
+        else
+          old_props = their_old_props;
+
+      /* We currently handle *_conflict as *_full as this argument is currently
+         always applied for all conflicts on a node at the same time. Giving
+         an error would break some tests that assumed that this would just
+         resolve property conflicts to working.
+
+         An alternative way to handle these conflicts would be to just copy all
+         property state from mine/theirs on the _full option instead of just the
+         conflicted properties. In some ways this feels like a sensible option as
+         that would take both properties and text from mine/theirs, but when not
+         both properties and text are conflicted we would fail in doing so.
+       */
+      switch (conflict_choice)
+        {
+        case svn_wc_conflict_choose_base:
+          resolve_from = their_old_props ? their_old_props : old_props;
+          break;
+        case svn_wc_conflict_choose_mine_full:
+        case svn_wc_conflict_choose_mine_conflict:
+          resolve_from = mine_props;
+          break;
+        case svn_wc_conflict_choose_theirs_full:
+        case svn_wc_conflict_choose_theirs_conflict:
+          resolve_from = their_props;
+          break;
+        case svn_wc_conflict_choose_merged:
+          resolve_from = NULL;
+          break;
+        default:
+          return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                  _("Invalid 'conflict_result' argument"));
+        }
+
+      if (conflicted_props && apr_hash_count(conflicted_props) && resolve_from)
+        {
+          apr_hash_index_t *hi;
+          apr_hash_t *actual_props;
+
+          SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath,
+                                        scratch_pool, scratch_pool));
+
+          for (hi = apr_hash_first(scratch_pool, conflicted_props);
+               hi;
+               hi = apr_hash_next(hi))
+            {
+              const char *propname = svn__apr_hash_index_key(hi);
+              svn_string_t *new_value = NULL;
+
+              new_value = apr_hash_get(resolve_from, propname,
+                                       APR_HASH_KEY_STRING);
+
+              apr_hash_set(actual_props, propname, APR_HASH_KEY_STRING,
+                           new_value);
+            }
+          SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props,
+                                          FALSE, NULL, NULL,
+                                          scratch_pool));
+        }
+
       /* Legacy behavior: Only report property conflicts as resolved when the
          property reject file exists
 
@@ -2280,6 +2501,7 @@ resolve_conflict_on_node(svn_boolean_t *
           if (node_kind == svn_node_file)
             {
               SVN_ERR(svn_wc__wq_build_file_remove(&work_item, db,
+                                                   local_abspath,
                                                    prop_reject_file,
                                                    pool, pool));
               work_items = svn_wc__wq_merge(work_items, work_item, pool);
@@ -2320,6 +2542,7 @@ svn_wc__resolve_text_conflict(svn_wc__db
                            FALSE /* resolve_props */,
                            FALSE /* resolve_tree */,
                            svn_wc_conflict_choose_merged,
+                           NULL,
                            NULL, NULL, /* cancel_func */
                            scratch_pool));
 }
@@ -2361,7 +2584,7 @@ conflict_status_walker(void *baton,
 
   iterpool = svn_pool_create(scratch_pool);
 
-  SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath,
+  SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath, TRUE,
                                  scratch_pool, iterpool));
 
   for (i = 0; i < conflicts->nelts; i++)
@@ -2369,6 +2592,8 @@ conflict_status_walker(void *baton,
       const svn_wc_conflict_description2_t *cd;
       svn_boolean_t did_resolve;
       svn_wc_conflict_choice_t my_choice = cswb->conflict_choice;
+      svn_skel_t *work_items = NULL;
+
 
       cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
 
@@ -2399,15 +2624,32 @@ conflict_status_walker(void *baton,
             if (!cswb->resolve_tree)
               break;
 
-            /* For now, we only clear tree conflict information and resolve
-             * to the working state. There is no way to pick theirs-full
-             * or mine-full, etc. Throw an error if the user expects us
-             * to be smarter than we really are. */
-            if (my_choice != svn_wc_conflict_choose_merged)
+            /* After updates, we can resolve local moved-away vs. any incoming
+             * change, either by updating the moved-away node (mine-conflict)
+             * or by breaking the move (theirs-conflict). */
+            if ((cd->operation == svn_wc_operation_update ||
+                 cd->operation == svn_wc_operation_switch) &&
+                cd->reason == svn_wc_conflict_reason_moved_away)
+              {
+                if (my_choice == svn_wc_conflict_choose_mine_conflict)
+                  SVN_ERR(svn_wc__update_moved_away_conflict_victim(
+                            &work_items, local_abspath, cswb->db,
+                            cswb->notify_func, cswb->notify_baton,
+                            cswb->cancel_func, cswb->cancel_baton,
+                            scratch_pool, scratch_pool));
+                 else if (my_choice == svn_wc_conflict_choose_theirs_conflict)
+                  {
+                    /* ### TODO break move */
+                  }
+              }
+            else if (my_choice != svn_wc_conflict_choose_merged)
               {
+                /* For other tree conflicts, there is no way to pick
+                 * theirs-full or mine-full, etc. Throw an error if the
+                 * user expects us to be smarter than we really are. */
                 return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
                                          NULL,
-                                         _("Tree conflicts can only be "
+                                         _("Tree conflict can only be "
                                            "resolved to 'working' state; "
                                            "'%s' not resolved"),
                                          svn_dirent_local_style(local_abspath,
@@ -2421,6 +2663,7 @@ conflict_status_walker(void *baton,
                                              FALSE /* resolve_props */,
                                              TRUE /* resolve_tree */,
                                              my_choice,
+                                             work_items,
                                              cswb->cancel_func,
                                              cswb->cancel_baton,
                                              iterpool));
@@ -2439,6 +2682,7 @@ conflict_status_walker(void *baton,
                                              FALSE /* resolve_props */,
                                              FALSE /* resolve_tree */,
                                              my_choice,
+                                             NULL,
                                              cswb->cancel_func,
                                              cswb->cancel_baton,
                                              iterpool));
@@ -2468,6 +2712,7 @@ conflict_status_walker(void *baton,
                                              TRUE /* resolve_props */,
                                              FALSE /* resolve_tree */,
                                              my_choice,
+                                             NULL,
                                              cswb->cancel_func,
                                              cswb->cancel_baton,
                                              iterpool));

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/conflicts.h Sun Oct 21 02:00:31 2012
@@ -260,6 +260,8 @@ svn_wc__conflict_skel_resolve(svn_boolea
  *
  * Output arguments can be NULL if the value is not necessary.
  *
+ * ### stsp asks: what is LOCATIONS?
+ *
  * TEXT_, PROP_ and TREE_CONFLICTED (when not NULL) will be set to TRUE
  * when the conflict contains the specified kind of conflict, otherwise
  * to false.
@@ -392,6 +394,20 @@ svn_wc__resolve_text_conflict(svn_wc__db
                               const char *local_abspath,
                               apr_pool_t *scratch_pool);
 
+/* Update a moved-away tree conflict victim at VICTIM_ABSPATH with changes
+ * brought in by the update operation which flagged the tree conflict.
+ * Set *WORK_ITEMS to a list of work items, allocated in RESULT_POOL, that
+ * need to run as part of marking the conflict resolved. */
+svn_error_t *
+svn_wc__update_moved_away_conflict_victim(svn_skel_t **work_items,
+                                          const char *victim_abspath,
+                                          svn_wc__db_t *db,
+                                          svn_wc_notify_func2_t notify_func,
+                                          void *notify_baton,
+                                          svn_cancel_func_t cancel_func,
+                                          void *cancel_baton,
+                                          apr_pool_t *result_pool,
+                                          apr_pool_t *scratch_pool);
 
 #ifdef __cplusplus
 }

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/copy.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/copy.c Sun Oct 21 02:00:31 2012
@@ -36,6 +36,7 @@
 #include "wc.h"
 #include "workqueue.h"
 #include "props.h"
+#include "conflicts.h"
 
 #include "svn_private_config.h"
 #include "private/svn_wc_private.h"
@@ -206,7 +207,6 @@ copy_versioned_file(svn_wc__db_t *db,
   if (!metadata_only)
     {
       const char *my_src_abspath = NULL;
-      int i;
       svn_boolean_t handle_as_unversioned = FALSE;
 
       /* By default, take the copy source as given. */
@@ -214,26 +214,27 @@ copy_versioned_file(svn_wc__db_t *db,
 
       if (conflicted)
         {
-          const apr_array_header_t *conflicts;
-          const char *conflict_working = NULL;
+          svn_skel_t *conflict;
+          const char *conflict_working;
+          svn_error_t *err;
 
           /* Is there a text conflict at the source path? */
-          SVN_ERR(svn_wc__read_conflicts(&conflicts, db, src_abspath,
+          SVN_ERR(svn_wc__db_read_conflict(&conflict, db, src_abspath,
                                          scratch_pool, scratch_pool));
 
-          for (i = 0; i < conflicts->nelts; i++)
-            {
-              const svn_wc_conflict_description2_t *desc;
-
-              desc = APR_ARRAY_IDX(conflicts, i,
-                                   const svn_wc_conflict_description2_t*);
+          err = svn_wc__conflict_read_text_conflict(&conflict_working, NULL, NULL,
+                                                    db, src_abspath, conflict,
+                                                    scratch_pool,
+                                                    scratch_pool);
 
-              if (desc->kind == svn_wc_conflict_kind_text)
-                {
-                  conflict_working = desc->my_abspath;
-                  break;
-                }
+          if (err && err->apr_err == SVN_ERR_WC_MISSING)
+            {
+              /* not text conflicted */
+              svn_error_clear(err);
+              conflict_working = NULL;
             }
+          else
+            SVN_ERR(err);
 
           if (conflict_working)
             {
@@ -287,7 +288,9 @@ copy_versioned_file(svn_wc__db_t *db,
    otherwise copy both the versioned metadata and the filesystem nodes (even
    if they are the wrong kind, and including unversioned children).
    If IS_MOVE is true, record move information in working copy meta
-   data in addition to copying the directory.
+   data in addition to copying the directory. If IS_MOVE is TRUE and
+   ALLOW_MIXED_REVISIONS is FALSE, raise an error if a move of a
+   mixed-revision subtree is attempted.
 
    WITHIN_ONE_WC is TRUE if the copy/move is within a single working copy (root)
  */
@@ -299,6 +302,7 @@ copy_versioned_dir(svn_wc__db_t *db,
                    const char *tmpdir_abspath,
                    svn_boolean_t metadata_only,
                    svn_boolean_t is_move,
+                   svn_boolean_t allow_mixed_revisions,
                    svn_boolean_t within_one_wc,
                    svn_cancel_func_t cancel_func,
                    void *cancel_baton,
@@ -315,6 +319,24 @@ copy_versioned_dir(svn_wc__db_t *db,
   svn_node_kind_t disk_kind;
   apr_pool_t *iterpool;
 
+  if (is_move && !allow_mixed_revisions)
+    {
+      svn_revnum_t min_rev;
+      svn_revnum_t max_rev;
+
+      /* Verify that the move source is a single-revision subtree. */
+      SVN_ERR(svn_wc__db_min_max_revisions(&min_rev, &max_rev, db,
+                                           src_abspath, FALSE, scratch_pool));
+      if (SVN_IS_VALID_REVNUM(min_rev) && SVN_IS_VALID_REVNUM(max_rev) &&
+          min_rev != max_rev)
+        return svn_error_createf(SVN_ERR_WC_MIXED_REVISIONS, NULL,
+                                 _("Cannot move mixed-revision subtree '%s' "
+                                   "[%lu:%lu]; try updating it first"),
+                                   svn_dirent_local_style(src_abspath,
+                                                          scratch_pool),
+                                   min_rev, max_rev);
+    }
+
   /* Prepare a temp copy of the single filesystem node (usually a dir). */
   if (!metadata_only)
     {
@@ -412,7 +434,8 @@ copy_versioned_dir(svn_wc__db_t *db,
             SVN_ERR(copy_versioned_dir(db,
                                        child_src_abspath, child_dst_abspath,
                                        dst_op_root_abspath, tmpdir_abspath,
-                                       metadata_only, is_move, within_one_wc,
+                                       metadata_only, is_move,
+                                       allow_mixed_revisions, within_one_wc,
                                        cancel_func, cancel_baton, NULL, NULL,
                                        iterpool));
           else
@@ -523,6 +546,7 @@ copy_or_move(svn_wc_context_t *wc_ctx,
              const char *dst_abspath,
              svn_boolean_t metadata_only,
              svn_boolean_t is_move,
+             svn_boolean_t allow_mixed_revisions,
              svn_cancel_func_t cancel_func,
              void *cancel_baton,
              svn_wc_notify_func2_t notify_func,
@@ -737,8 +761,8 @@ copy_or_move(svn_wc_context_t *wc_ctx,
   else
     {
       err = copy_versioned_dir(db, src_abspath, dst_abspath, dst_abspath,
-                               tmpdir_abspath,
-                               metadata_only, is_move, within_one_wc,
+                               tmpdir_abspath, metadata_only, is_move,
+                               allow_mixed_revisions, within_one_wc,
                                cancel_func, cancel_baton,
                                notify_func, notify_baton,
                                scratch_pool);
@@ -773,6 +797,7 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
 {
   return svn_error_trace(copy_or_move(wc_ctx, src_abspath, dst_abspath,
                                       metadata_only, FALSE /* is_move */,
+                                      TRUE /* allow_mixed_revisions */,
                                       cancel_func, cancel_baton,
                                       notify_func, notify_baton,
                                       scratch_pool));
@@ -792,75 +817,40 @@ remove_node_conflict_markers(svn_wc__db_
                              const char *node_abspath,
                              apr_pool_t *scratch_pool)
 {
-  const apr_array_header_t *conflicts;
+  svn_skel_t *conflict;
 
-  SVN_ERR(svn_wc__read_conflicts(&conflicts, db, src_abspath,
+  SVN_ERR(svn_wc__db_read_conflict(&conflict, db, src_abspath,
                                  scratch_pool, scratch_pool));
 
   /* Do we have conflict markers that should be removed? */
-  if (conflicts != NULL)
+  if (conflict != NULL)
     {
+      const apr_array_header_t *markers;
       int i;
       const char *src_dir = svn_dirent_dirname(src_abspath, scratch_pool);
       const char *dst_dir = svn_dirent_dirname(node_abspath, scratch_pool);
 
-      /* No iterpool: Maximum number of possible conflict markers is 4 */
+      SVN_ERR(svn_wc__conflict_read_markers(&markers, db, src_abspath,
+                                            conflict,
+                                            scratch_pool, scratch_pool));
 
-      for (i = 0; i < conflicts->nelts; i++)
+      /* No iterpool: Maximum number of possible conflict markers is 4 */
+      for (i = 0; markers && (i < markers->nelts); i++)
         {
-          const svn_wc_conflict_description2_t *desc;
+          const char *marker_abspath;
           const char *child_relpath;
           const char *child_abpath;
 
-          desc = APR_ARRAY_IDX(conflicts, i,
-                               const svn_wc_conflict_description2_t*);
-
-          if (desc->kind != svn_wc_conflict_kind_text
-              && desc->kind != svn_wc_conflict_kind_property)
-            continue;
-
-          if (desc->base_abspath != NULL)
-            {
-              child_relpath = svn_dirent_is_child(src_dir, desc->base_abspath,
-                                                  NULL);
+          marker_abspath = APR_ARRAY_IDX(markers, i, const char *);
 
-              if (child_relpath)
-                {
-                  child_abpath = svn_dirent_join(dst_dir, child_relpath,
-                                                 scratch_pool);
+          child_relpath = svn_dirent_is_child(src_dir, marker_abspath, NULL);
 
-                  SVN_ERR(svn_io_remove_file2(child_abpath, TRUE,
-                                              scratch_pool));
-                }
-            }
-          if (desc->their_abspath != NULL)
+          if (child_relpath)
             {
-              child_relpath = svn_dirent_is_child(src_dir, desc->their_abspath,
-                                                  NULL);
-
-              if (child_relpath)
-                {
-                  child_abpath = svn_dirent_join(dst_dir, child_relpath,
-                                                 scratch_pool);
+              child_abpath = svn_dirent_join(dst_dir, child_relpath,
+                                             scratch_pool);
 
-                  SVN_ERR(svn_io_remove_file2(child_abpath, TRUE,
-                                              scratch_pool));
-                }
-            }
-          if (desc->my_abspath != NULL)
-            {
-              child_relpath = svn_dirent_is_child(src_dir, desc->my_abspath,
-                                                  NULL);
-
-              if (child_relpath)
-                {
-                  child_abpath = svn_dirent_join(dst_dir, child_relpath,
-                                                 scratch_pool);
-
-                  /* ### Copy child_abspath to node_abspath if it exists? */
-                  SVN_ERR(svn_io_remove_file2(child_abpath, TRUE,
-                                              scratch_pool));
-                }
+              SVN_ERR(svn_io_remove_file2(child_abpath, TRUE, scratch_pool));
             }
         }
     }
@@ -928,21 +918,23 @@ remove_all_conflict_markers(svn_wc__db_t
 }
 
 svn_error_t *
-svn_wc_move(svn_wc_context_t *wc_ctx,
-            const char *src_abspath,
-            const char *dst_abspath,
-            svn_boolean_t metadata_only,
-            svn_cancel_func_t cancel_func,
-            void *cancel_baton,
-            svn_wc_notify_func2_t notify_func,
-            void *notify_baton,
-            apr_pool_t *scratch_pool)
+svn_wc__move2(svn_wc_context_t *wc_ctx,
+              const char *src_abspath,
+              const char *dst_abspath,
+              svn_boolean_t metadata_only,
+              svn_boolean_t allow_mixed_revisions,
+              svn_cancel_func_t cancel_func,
+              void *cancel_baton,
+              svn_wc_notify_func2_t notify_func,
+              void *notify_baton,
+              apr_pool_t *scratch_pool)
 {
   svn_wc__db_t *db = wc_ctx->db;
 
   SVN_ERR(copy_or_move(wc_ctx, src_abspath, dst_abspath,
                        TRUE /* metadata_only */,
                        TRUE /* is_move */,
+                       allow_mixed_revisions,
                        cancel_func, cancel_baton,
                        notify_func, notify_baton,
                        scratch_pool));

Modified: subversion/branches/ev2-export/subversion/libsvn_wc/crop.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_wc/crop.c?rev=1400556&r1=1400555&r2=1400556&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_wc/crop.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_wc/crop.c Sun Oct 21 02:00:31 2012
@@ -31,24 +31,10 @@
 #include "svn_path.h"
 
 #include "wc.h"
+#include "workqueue.h"
 
 #include "svn_private_config.h"
 
-/* Evaluate EXPR.  If it returns an error, return that error, unless
-   the error's code is SVN_ERR_WC_LEFT_LOCAL_MOD, in which case clear
-   the error and do not return. */
-#define IGNORE_LOCAL_MOD(expr)                                   \
-  do {                                                           \
-    svn_error_t *__temp = (expr);                                \
-    if (__temp)                                                  \
-      {                                                          \
-        if (__temp->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)        \
-          svn_error_clear(__temp);                               \
-        else                                                     \
-          return svn_error_trace(__temp);                       \
-      }                                                          \
-  } while (0)
-
 /* Helper function that crops the children of the LOCAL_ABSPATH, under the
  * constraint of NEW_DEPTH. The DIR_PATH itself will never be cropped. The
  * whole subtree should have been locked.
@@ -121,29 +107,25 @@ crop_children(svn_wc__db_t *db,
                                             ? svn_depth_immediates
                                             : svn_depth_files;
           if (new_depth < remove_below)
-            SVN_ERR(svn_wc__db_op_remove_node(db, local_abspath,
-                                              SVN_INVALID_REVNUM,
-                                              svn_kind_unknown,
-                                              iterpool));
+            SVN_ERR(svn_wc__db_base_remove(db, local_abspath, FALSE,
+                                           SVN_INVALID_REVNUM,
+                                           NULL, NULL, iterpool));
 
           continue;
         }
       else if (kind == svn_kind_file)
         {
-          /* We currently crop on a directory basis. So don't worry about
-             svn_depth_exclude here. And even we permit excluding a single
-             file in the future, svn_wc_remove_from_revision_control() can
-             also handle it. We only need to skip the notification in that
-             case. */
           if (new_depth == svn_depth_empty)
-            IGNORE_LOCAL_MOD(
-              svn_wc__internal_remove_from_revision_control(
-                                                   db,
-                                                   child_abspath,
-                                                   TRUE, /* destroy */
-                                                   FALSE, /* instant error */
-                                                   cancel_func, cancel_baton,
-                                                   iterpool));
+            SVN_ERR(svn_wc__db_op_remove_node(NULL,
+                                              db, child_abspath,
+                                              TRUE /* destroy */,
+                                              FALSE /* destroy_changes */,
+                                              SVN_INVALID_REVNUM,
+                                              svn_wc__db_status_not_present,
+                                              svn_kind_none,
+                                              NULL, NULL,
+                                              cancel_func, cancel_baton,
+                                              iterpool));
           else
             continue;
 
@@ -152,15 +134,16 @@ crop_children(svn_wc__db_t *db,
         {
           if (new_depth < svn_depth_immediates)
             {
-              IGNORE_LOCAL_MOD(
-                svn_wc__internal_remove_from_revision_control(
-                                                     db,
-                                                     child_abspath,
-                                                     TRUE, /* destroy */
-                                                     FALSE, /* instant error */
-                                                     cancel_func,
-                                                     cancel_baton,
-                                                     iterpool));
+              SVN_ERR(svn_wc__db_op_remove_node(NULL,
+                                                db, child_abspath,
+                                                TRUE /* destroy */,
+                                                FALSE /* destroy_changes */,
+                                                SVN_INVALID_REVNUM,
+                                                svn_wc__db_status_not_present,
+                                                svn_kind_none,
+                                                NULL, NULL,
+                                                cancel_func, cancel_baton,
+                                                iterpool));
             }
           else
             {
@@ -272,27 +255,21 @@ svn_wc_exclude(svn_wc_context_t *wc_ctx,
         break; /* Ok to exclude */
     }
 
-  /* ### This could use some kind of transaction */
-
   /* Remove all working copy data below local_abspath */
-  IGNORE_LOCAL_MOD(svn_wc__internal_remove_from_revision_control(
-                                    wc_ctx->db,
-                                    local_abspath,
-                                    TRUE,
-                                    FALSE,
+  SVN_ERR(svn_wc__db_op_remove_node(NULL,
+                                    wc_ctx->db, local_abspath,
+                                    TRUE /* destroy */,
+                                    FALSE /* destroy_changes */,
+                                    revision,
+                                    svn_wc__db_status_excluded,
+                                    kind,
+                                    NULL, NULL,
                                     cancel_func, cancel_baton,
                                     scratch_pool));
 
-  SVN_ERR(svn_wc__db_base_add_excluded_node(wc_ctx->db,
-                                            local_abspath,
-                                            repos_relpath,
-                                            repos_root,
-                                            repos_uuid,
-                                            revision,
-                                            kind,
-                                            svn_wc__db_status_excluded,
-                                            NULL, NULL,
-                                            scratch_pool));
+  SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath,
+                         cancel_func, cancel_baton,
+                         scratch_pool));
 
   if (notify_func)
     {
@@ -372,7 +349,11 @@ svn_wc_crop_tree2(svn_wc_context_t *wc_c
         SVN_ERR_MALFUNCTION();
     }
 
-  return crop_children(db, local_abspath, dir_depth, depth,
-                       notify_func, notify_baton,
-                       cancel_func, cancel_baton, scratch_pool);
+  SVN_ERR(crop_children(db, local_abspath, dir_depth, depth,
+                        notify_func, notify_baton,
+                        cancel_func, cancel_baton, scratch_pool));
+
+  return svn_error_trace(svn_wc__wq_run(db, local_abspath,
+                                        cancel_func, cancel_baton,
+                                        scratch_pool));
 }