You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2014/09/03 11:14:59 UTC

svn commit: r1622195 [2/3] - in /subversion/branches/move-tracking-2: ./ build/ notes/ notes/wc-ng/ subversion/bindings/ctypes-python/ subversion/bindings/cxxhl/ subversion/bindings/swig/ subversion/bindings/swig/include/ subversion/include/ subversion...

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_editor.c Wed Sep  3 09:14:58 2014
@@ -115,9 +115,6 @@ struct edit_baton_t
   /* Possibly diff repos against text-bases instead of working files. */
   svn_boolean_t diff_pristine;
 
-  /* Hash whose keys are const char * changelist names. */
-  apr_hash_t *changelist_hash;
-
   /* Cancel function/baton */
   svn_cancel_func_t cancel_func;
   void *cancel_baton;
@@ -239,11 +236,6 @@ struct file_baton_t
  * calculating diffs.  USE_TEXT_BASE defines whether to compare
  * against working files or text-bases.  REVERSE_ORDER defines which
  * direction to perform the diff.
- *
- * CHANGELIST_FILTER is a list of const char * changelist names, used to
- * filter diff output responses to only those items in one of the
- * specified changelists, empty (or NULL altogether) if no changelist
- * filtering is requested.
  */
 static svn_error_t *
 make_edit_baton(struct edit_baton_t **edit_baton,
@@ -255,20 +247,14 @@ make_edit_baton(struct edit_baton_t **ed
                 svn_boolean_t ignore_ancestry,
                 svn_boolean_t use_text_base,
                 svn_boolean_t reverse_order,
-                const apr_array_header_t *changelist_filter,
                 svn_cancel_func_t cancel_func,
                 void *cancel_baton,
                 apr_pool_t *pool)
 {
-  apr_hash_t *changelist_hash = NULL;
   struct edit_baton_t *eb;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(anchor_abspath));
 
-  if (changelist_filter && changelist_filter->nelts)
-    SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
-                                       pool));
-
   eb = apr_pcalloc(pool, sizeof(*eb));
   eb->db = db;
   eb->anchor_abspath = apr_pstrdup(pool, anchor_abspath);
@@ -278,7 +264,6 @@ make_edit_baton(struct edit_baton_t **ed
   eb->ignore_ancestry = ignore_ancestry;
   eb->local_before_remote = reverse_order;
   eb->diff_pristine = use_text_base;
-  eb->changelist_hash = changelist_hash;
   eb->cancel_func = cancel_func;
   eb->cancel_baton = cancel_baton;
   eb->pool = pool;
@@ -392,7 +377,6 @@ svn_wc__diff_base_working_diff(svn_wc__d
                                const char *local_abspath,
                                const char *relpath,
                                svn_revnum_t revision,
-                               apr_hash_t *changelist_hash,
                                const svn_diff_tree_processor_t *processor,
                                void *processor_dir_baton,
                                svn_boolean_t diff_pristine,
@@ -419,12 +403,11 @@ svn_wc__diff_base_working_diff(svn_wc__d
   apr_hash_t *base_props;
   apr_hash_t *local_props;
   apr_array_header_t *prop_changes;
-  const char *changelist;
 
   SVN_ERR(svn_wc__db_read_info(&status, NULL, &db_revision, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, &working_checksum, NULL,
                                NULL, NULL, NULL, NULL, NULL, &recorded_size,
-                               &recorded_time, &changelist, NULL, NULL,
+                               &recorded_time, NULL, NULL, NULL,
                                &had_props, &props_mod, NULL, NULL, NULL,
                                db, local_abspath, scratch_pool, scratch_pool));
   checksum = working_checksum;
@@ -433,12 +416,6 @@ svn_wc__diff_base_working_diff(svn_wc__d
          || status == svn_wc__db_status_added
          || (status == svn_wc__db_status_deleted && diff_pristine));
 
-  /* If the item is not a member of a specified changelist (and there are
-     some specified changelists), skip it. */
-  if (changelist_hash && !svn_hash_gets(changelist_hash, changelist))
-    return SVN_NO_ERROR;
-
-
   if (status != svn_wc__db_status_normal)
     {
       SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, &db_revision,
@@ -768,7 +745,6 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
                                                      eb->processor, dir_baton,
-                                                     eb->changelist_hash,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
                                                      eb->cancel_baton,
@@ -778,7 +754,6 @@ walk_local_nodes_diff(struct edit_baton_
                                                     child_relpath,
                                                     depth_below_here,
                                                     eb->processor, dir_baton,
-                                                    eb->changelist_hash,
                                                     eb->diff_pristine,
                                                     eb->cancel_func,
                                                     eb->cancel_baton,
@@ -814,7 +789,6 @@ walk_local_nodes_diff(struct edit_baton_
                                                 db, child_abspath,
                                                 child_relpath,
                                                 eb->revnum,
-                                                eb->changelist_hash,
                                                 eb->processor, dir_baton,
                                                 eb->diff_pristine,
                                                 eb->cancel_func,
@@ -837,7 +811,6 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
                                                      child_relpath,
                                                      eb->processor, dir_baton,
-                                                     eb->changelist_hash,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
                                                      eb->cancel_baton,
@@ -846,7 +819,6 @@ walk_local_nodes_diff(struct edit_baton_
                 SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
                                                      child_relpath, depth_below_here,
                                                      eb->processor, dir_baton,
-                                                     eb->changelist_hash,
                                                      eb->diff_pristine,
                                                      eb->cancel_func,
                                                      eb->cancel_baton,
@@ -858,13 +830,9 @@ walk_local_nodes_diff(struct edit_baton_
   if (compared)
     return SVN_NO_ERROR;
 
-    /* Check for local property mods on this directory, if we haven't
-     already reported them and we aren't changelist-filted.
-     ### it should be noted that we do not currently allow directories
-     ### to be part of changelists, so if a changelist is provided, the
-     ### changelist check will always fail. */
+  /* Check for local property mods on this directory, if we haven't
+     already reported them. */
   if (! skip
-      && ! eb->changelist_hash
       && ! in_anchor_not_target
       && props_mod)
     {
@@ -907,7 +875,6 @@ svn_wc__diff_local_only_file(svn_wc__db_
                              const char *relpath,
                              const svn_diff_tree_processor_t *processor,
                              void *processor_parent_baton,
-                             apr_hash_t *changelist_hash,
                              svn_boolean_t diff_pristine,
                              svn_cancel_func_t cancel_func,
                              void *cancel_baton,
@@ -920,7 +887,6 @@ svn_wc__diff_local_only_file(svn_wc__db_
   const svn_checksum_t *checksum;
   const char *original_repos_relpath;
   svn_revnum_t original_revision;
-  const char *changelist;
   svn_boolean_t had_props;
   svn_boolean_t props_mod;
   apr_hash_t *pristine_props;
@@ -936,7 +902,7 @@ svn_wc__diff_local_only_file(svn_wc__db_
                                NULL, NULL, NULL, NULL, &checksum, NULL,
                                &original_repos_relpath, NULL, NULL,
                                &original_revision, NULL, NULL, NULL,
-                               &changelist, NULL, NULL, &had_props,
+                               NULL, NULL, NULL, &had_props,
                                &props_mod, NULL, NULL, NULL,
                                db, local_abspath,
                                scratch_pool, scratch_pool));
@@ -947,10 +913,6 @@ svn_wc__diff_local_only_file(svn_wc__db_
              || (status == svn_wc__db_status_deleted && diff_pristine)));
 
 
-  if (changelist && changelist_hash
-      && !svn_hash_gets(changelist_hash, changelist))
-    return SVN_NO_ERROR;
-
   if (status == svn_wc__db_status_deleted)
     {
       assert(diff_pristine);
@@ -1053,12 +1015,19 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                             svn_depth_t depth,
                             const svn_diff_tree_processor_t *processor,
                             void *processor_parent_baton,
-                            apr_hash_t *changelist_hash,
                             svn_boolean_t diff_pristine,
                             svn_cancel_func_t cancel_func,
                             void *cancel_baton,
                             apr_pool_t *scratch_pool)
 {
+  svn_wc__db_status_t status;
+  svn_node_kind_t kind;
+  svn_boolean_t had_props;
+  svn_boolean_t props_mod;
+  const char *original_repos_relpath;
+  svn_revnum_t original_revision;
+  svn_diff_source_t *copyfrom_src = NULL;
+  apr_hash_t *pristine_props;
   const apr_array_header_t *children;
   int i;
   apr_pool_t *iterpool;
@@ -1067,9 +1036,43 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
   svn_boolean_t skip_children = FALSE;
   svn_diff_source_t *right_src = svn_diff__source_create(SVN_INVALID_REVNUM,
                                                          scratch_pool);
-  svn_depth_t depth_below_here = depth;
-  apr_hash_t *nodes;
-  apr_hash_t *conflicts;
+
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               &original_repos_relpath, NULL, NULL,
+                               &original_revision, NULL, NULL, NULL,
+                               NULL, NULL, NULL, &had_props,
+                               &props_mod, NULL, NULL, NULL,
+                               db, local_abspath,
+                               scratch_pool, scratch_pool));
+  if (original_repos_relpath)
+    {
+      copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);
+      copyfrom_src->repos_relpath = original_repos_relpath;
+    }
+
+  assert(kind == svn_node_dir
+         && (status == svn_wc__db_status_normal
+             || status == svn_wc__db_status_added
+             || (status == svn_wc__db_status_deleted && diff_pristine)));
+
+  if (status == svn_wc__db_status_deleted)
+    {
+      assert(diff_pristine);
+
+      SVN_ERR(svn_wc__db_read_pristine_info(NULL, NULL, NULL, NULL, NULL,
+                                            NULL, NULL, NULL, &had_props,
+                                            &pristine_props,
+                                            db, local_abspath,
+                                            scratch_pool, scratch_pool));
+      props_mod = FALSE;
+    }
+  else if (!had_props)
+    pristine_props = apr_hash_make(scratch_pool);
+  else
+    SVN_ERR(svn_wc__db_read_pristine_props(&pristine_props,
+                                           db, local_abspath,
+                                           scratch_pool, scratch_pool));
 
   /* Report the addition of the directory's contents. */
   iterpool = svn_pool_create(scratch_pool);
@@ -1078,76 +1081,86 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                                 relpath,
                                 NULL,
                                 right_src,
-                                NULL /* copyfrom_src */,
+                                copyfrom_src,
                                 processor_parent_baton,
                                 processor,
                                 scratch_pool, iterpool));
 
-  SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts, db, local_abspath,
-                                        FALSE /* base_tree_only */,
-                                        scratch_pool, iterpool));
-
-  if (depth_below_here == svn_depth_immediates)
-    depth_below_here = svn_depth_empty;
-
-  children = svn_sort__hash(nodes, svn_sort_compare_items_lexically,
-                            scratch_pool);
-
-  for (i = 0; i < children->nelts; i++)
+  if ((depth > svn_depth_empty || depth == svn_depth_unknown)
+      && ! skip_children)
     {
-      svn_sort__item_t *item = &APR_ARRAY_IDX(children, i, svn_sort__item_t);
-      const char *name = item->key;
-      struct svn_wc__db_info_t *info = item->value;
-      const char *child_abspath;
-      const char *child_relpath;
+      svn_depth_t depth_below_here = depth;
+      apr_hash_t *nodes;
+      apr_hash_t *conflicts;
 
-      svn_pool_clear(iterpool);
+      if (depth_below_here == svn_depth_immediates)
+        depth_below_here = svn_depth_empty;
+
+      SVN_ERR(svn_wc__db_read_children_info(&nodes, &conflicts,
+                                            db, local_abspath,
+                                            FALSE /* base_tree_only */,
+                                            scratch_pool, iterpool));
 
-      if (cancel_func)
-        SVN_ERR(cancel_func(cancel_baton));
 
-      child_abspath = svn_dirent_join(local_abspath, name, iterpool);
+      children = svn_sort__hash(nodes, svn_sort_compare_items_lexically,
+                                scratch_pool);
 
-      if (NOT_PRESENT(info->status))
+      for (i = 0; i < children->nelts; i++)
         {
-          continue;
-        }
+          svn_sort__item_t *item = &APR_ARRAY_IDX(children, i, svn_sort__item_t);
+          const char *name = item->key;
+          struct svn_wc__db_info_t *info = item->value;
+          const char *child_abspath;
+          const char *child_relpath;
 
-      /* If comparing against WORKING, skip entries that are
-         schedule-deleted - they don't really exist. */
-      if (!diff_pristine && info->status == svn_wc__db_status_deleted)
-        continue;
+          svn_pool_clear(iterpool);
 
-      child_relpath = svn_relpath_join(relpath, name, iterpool);
+          if (cancel_func)
+            SVN_ERR(cancel_func(cancel_baton));
 
-      switch (info->kind)
-        {
-        case svn_node_file:
-        case svn_node_symlink:
-          SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
-                                               child_relpath,
-                                               processor, pdb,
-                                               changelist_hash,
-                                               diff_pristine,
-                                               cancel_func, cancel_baton,
-                                               scratch_pool));
-          break;
+          child_abspath = svn_dirent_join(local_abspath, name, iterpool);
 
-        case svn_node_dir:
-          if (depth > svn_depth_files || depth == svn_depth_unknown)
+          if (NOT_PRESENT(info->status))
             {
-              SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
-                                                  child_relpath, depth_below_here,
-                                                  processor, pdb,
-                                                  changelist_hash,
-                                                  diff_pristine,
-                                                  cancel_func, cancel_baton,
-                                                  iterpool));
+              continue;
             }
-          break;
 
-        default:
-          break;
+          /* If comparing against WORKING, skip entries that are
+             schedule-deleted - they don't really exist. */
+          if (!diff_pristine && info->status == svn_wc__db_status_deleted)
+            continue;
+
+          child_relpath = svn_relpath_join(relpath, name, iterpool);
+
+          switch (info->kind)
+            {
+            case svn_node_file:
+            case svn_node_symlink:
+              SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,
+                                                   child_relpath,
+                                                   processor, pdb,
+                                                   diff_pristine,
+                                                   cancel_func, cancel_baton,
+                                                   scratch_pool));
+              break;
+
+            case svn_node_dir:
+              if (depth > svn_depth_files || depth == svn_depth_unknown)
+                {
+                  SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,
+                                                      child_relpath,
+                                                      depth_below_here,
+                                                      processor, pdb,
+                                                      diff_pristine,
+                                                      cancel_func,
+                                                      cancel_baton,
+                                                      iterpool));
+                }
+              break;
+
+            default:
+              break;
+            }
         }
     }
 
@@ -1162,9 +1175,11 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
                                          scratch_pool, scratch_pool));
 
       SVN_ERR(processor->dir_added(relpath,
-                                   NULL /* copyfrom_src */,
+                                   copyfrom_src,
                                    right_src,
-                                   NULL,
+                                   copyfrom_src
+                                     ? pristine_props
+                                     : NULL,
                                    right_props,
                                    pdb,
                                    processor,
@@ -1235,7 +1250,6 @@ handle_local_only(struct dir_baton_t *pb
                       svn_relpath_join(pb->relpath, name, scratch_pool),
                       repos_delete ? svn_depth_infinity : depth,
                       eb->processor, pb->pdb,
-                      eb->changelist_hash,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,
                       scratch_pool));
@@ -1246,7 +1260,6 @@ handle_local_only(struct dir_baton_t *pb
                       svn_dirent_join(pb->local_abspath, name, scratch_pool),
                       svn_relpath_join(pb->relpath, name, scratch_pool),
                       eb->processor, pb->pdb,
-                      eb->changelist_hash,
                       eb->diff_pristine,
                       eb->cancel_func, eb->cancel_baton,
                       scratch_pool));
@@ -2021,7 +2034,14 @@ close_file(void *file_baton,
   const char *repos_file;
   apr_hash_t *repos_props;
 
-  if (!fb->skip && expected_md5_digest != NULL)
+  if (fb->skip)
+    {
+      svn_pool_destroy(fb->pool); /* destroys scratch_pool and fb */
+      SVN_ERR(maybe_done(pb));
+      return SVN_NO_ERROR;
+    }
+
+  if (expected_md5_digest != NULL)
     {
       svn_checksum_t *expected_checksum;
       const svn_checksum_t *result_checksum;
@@ -2076,11 +2096,7 @@ close_file(void *file_baton,
       }
   }
 
-  if (fb->skip)
-    {
-      /* Diff processor requested skipping information */
-    }
-  else if (fb->repos_only)
+  if (fb->repos_only)
     {
       SVN_ERR(eb->processor->file_deleted(fb->relpath,
                                           fb->left_src,
@@ -2260,12 +2276,24 @@ svn_wc__get_diff_editor(const svn_delta_
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(anchor_abspath));
 
+  /* Apply changelist filtering to the output */
+  if (changelist_filter && changelist_filter->nelts)
+    {
+      apr_hash_t *changelist_hash;
+
+      SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
+                                         result_pool));
+      diff_processor = svn_wc__changelist_filter_tree_processor_create(
+                         diff_processor, wc_ctx, anchor_abspath,
+                         changelist_hash, result_pool);
+    }
+
   SVN_ERR(make_edit_baton(&eb,
                           wc_ctx->db,
                           anchor_abspath, target,
                           diff_processor,
                           depth, ignore_ancestry,
-                          use_text_base, reverse_order, changelist_filter,
+                          use_text_base, reverse_order,
                           cancel_func, cancel_baton,
                           result_pool));
 
@@ -2731,3 +2759,329 @@ svn_wc__wrap_diff_callbacks(const svn_di
   *diff_processor = processor;
   return SVN_NO_ERROR;
 }
+
+/* =====================================================================
+ * A tree processor filter that filters by changelist membership
+ * =====================================================================
+ *
+ * The current implementation queries the WC for the changelist of each
+ * file as it comes through, and sets the 'skip' flag for a non-matching
+ * file.
+ *
+ * (It doesn't set the 'skip' flag for a directory, as we need to receive
+ * the changed/added/deleted/closed call to know when it is closed, in
+ * order to preserve the strict open-close semantics for the wrapped tree
+ * processor.)
+ *
+ * It passes on the opening and closing of every directory, even if there
+ * are no file changes to be passed on inside that directory.
+ */
+
+typedef struct filter_tree_baton_t
+{
+  const svn_diff_tree_processor_t *processor;
+  svn_wc_context_t *wc_ctx;
+  /* WC path of the root of the diff (where relpath = "") */
+  const char *root_local_abspath;
+  /* Hash whose keys are const char * changelist names. */
+  apr_hash_t *changelist_hash;
+} filter_tree_baton_t;
+
+static svn_error_t *
+filter_dir_opened(void **new_dir_baton,
+                  svn_boolean_t *skip,
+                  svn_boolean_t *skip_children,
+                  const char *relpath,
+                  const svn_diff_source_t *left_source,
+                  const svn_diff_source_t *right_source,
+                  const svn_diff_source_t *copyfrom_source,
+                  void *parent_dir_baton,
+                  const svn_diff_tree_processor_t *processor,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->dir_opened(new_dir_baton, skip, skip_children,
+                                    relpath,
+                                    left_source, right_source,
+                                    copyfrom_source,
+                                    parent_dir_baton,
+                                    fb->processor,
+                                    result_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_added(const char *relpath,
+                 const svn_diff_source_t *copyfrom_source,
+                 const svn_diff_source_t *right_source,
+                 /*const*/ apr_hash_t *copyfrom_props,
+                 /*const*/ apr_hash_t *right_props,
+                 void *dir_baton,
+                 const svn_diff_tree_processor_t *processor,
+                 apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->dir_closed(relpath,
+                                    NULL,
+                                    right_source,
+                                    dir_baton,
+                                    fb->processor,
+                                    scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_deleted(const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   /*const*/ apr_hash_t *left_props,
+                   void *dir_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->dir_closed(relpath,
+                                    left_source,
+                                    NULL,
+                                    dir_baton,
+                                    fb->processor,
+                                    scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_changed(const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   const svn_diff_source_t *right_source,
+                   /*const*/ apr_hash_t *left_props,
+                   /*const*/ apr_hash_t *right_props,
+                   const apr_array_header_t *prop_changes,
+                   void *dir_baton,
+                   const struct svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->dir_closed(relpath,
+                                    left_source,
+                                    right_source,
+                                    dir_baton,
+                                    fb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_dir_closed(const char *relpath,
+                  const svn_diff_source_t *left_source,
+                  const svn_diff_source_t *right_source,
+                  void *dir_baton,
+                  const svn_diff_tree_processor_t *processor,
+                  apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->dir_closed(relpath,
+                                    left_source,
+                                    right_source,
+                                    dir_baton,
+                                    fb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_opened(void **new_file_baton,
+                   svn_boolean_t *skip,
+                   const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   const svn_diff_source_t *right_source,
+                   const svn_diff_source_t *copyfrom_source,
+                   void *dir_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *result_pool,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+  const char *local_abspath
+    = svn_dirent_join(fb->root_local_abspath, relpath, scratch_pool);
+
+  /* Skip if not a member of a given changelist */
+  if (! svn_wc__changelist_match(fb->wc_ctx, local_abspath,
+                                 fb->changelist_hash, scratch_pool))
+    {
+      *skip = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(fb->processor->file_opened(new_file_baton,
+                                     skip,
+                                     relpath,
+                                     left_source,
+                                     right_source,
+                                     copyfrom_source,
+                                     dir_baton,
+                                     fb->processor,
+                                     result_pool,
+                                     scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_added(const char *relpath,
+                  const svn_diff_source_t *copyfrom_source,
+                  const svn_diff_source_t *right_source,
+                  const char *copyfrom_file,
+                  const char *right_file,
+                  /*const*/ apr_hash_t *copyfrom_props,
+                  /*const*/ apr_hash_t *right_props,
+                  void *file_baton,
+                  const svn_diff_tree_processor_t *processor,
+                  apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->file_added(relpath,
+                                    copyfrom_source,
+                                    right_source,
+                                    copyfrom_file,
+                                    right_file,
+                                    copyfrom_props,
+                                    right_props,
+                                    file_baton,
+                                    fb->processor,
+                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_deleted(const char *relpath,
+                    const svn_diff_source_t *left_source,
+                    const char *left_file,
+                    /*const*/ apr_hash_t *left_props,
+                    void *file_baton,
+                    const svn_diff_tree_processor_t *processor,
+                    apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->file_deleted(relpath,
+                                      left_source,
+                                      left_file,
+                                      left_props,
+                                      file_baton,
+                                      fb->processor,
+                                      scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_changed(const char *relpath,
+                    const svn_diff_source_t *left_source,
+                    const svn_diff_source_t *right_source,
+                    const char *left_file,
+                    const char *right_file,
+                    /*const*/ apr_hash_t *left_props,
+                    /*const*/ apr_hash_t *right_props,
+                    svn_boolean_t file_modified,
+                    const apr_array_header_t *prop_changes,
+                    void *file_baton,
+                    const svn_diff_tree_processor_t *processor,
+                    apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->file_changed(relpath,
+                                      left_source,
+                                      right_source,
+                                      left_file,
+                                      right_file,
+                                      left_props,
+                                      right_props,
+                                      file_modified,
+                                      prop_changes,
+                                      file_baton,
+                                      fb->processor,
+                                      scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_file_closed(const char *relpath,
+                   const svn_diff_source_t *left_source,
+                   const svn_diff_source_t *right_source,
+                   void *file_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->file_closed(relpath,
+                                     left_source,
+                                     right_source,
+                                     file_baton,
+                                     fb->processor,
+                                     scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+filter_node_absent(const char *relpath,
+                   void *dir_baton,
+                   const svn_diff_tree_processor_t *processor,
+                   apr_pool_t *scratch_pool)
+{
+  struct filter_tree_baton_t *fb = processor->baton;
+
+  SVN_ERR(fb->processor->node_absent(relpath,
+                                     dir_baton,
+                                     fb->processor,
+                                     scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+const svn_diff_tree_processor_t *
+svn_wc__changelist_filter_tree_processor_create(
+                                const svn_diff_tree_processor_t *processor,
+                                svn_wc_context_t *wc_ctx,
+                                const char *root_local_abspath,
+                                apr_hash_t *changelist_hash,
+                                apr_pool_t *result_pool)
+{
+  struct filter_tree_baton_t *fb;
+  svn_diff_tree_processor_t *filter;
+
+  if (! changelist_hash)
+    return processor;
+
+  fb = apr_pcalloc(result_pool, sizeof(*fb));
+  fb->processor = processor;
+  fb->wc_ctx = wc_ctx;
+  fb->root_local_abspath = root_local_abspath;
+  fb->changelist_hash = changelist_hash;
+
+  filter = svn_diff__tree_processor_create(fb, result_pool);
+  filter->dir_opened   = filter_dir_opened;
+  filter->dir_added    = filter_dir_added;
+  filter->dir_deleted  = filter_dir_deleted;
+  filter->dir_changed  = filter_dir_changed;
+  filter->dir_closed   = filter_dir_closed;
+
+  filter->file_opened   = filter_file_opened;
+  filter->file_added    = filter_file_added;
+  filter->file_deleted  = filter_file_deleted;
+  filter->file_changed  = filter_file_changed;
+  filter->file_closed   = filter_file_closed;
+
+  filter->node_absent   = filter_node_absent;
+
+  return filter;
+}
+

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/diff_local.c Wed Sep  3 09:14:58 2014
@@ -1,6 +1,6 @@
 /*
- * diff_pristine.c -- A simple diff walker which compares local files against
- *                    their pristine versions.
+ * diff_local.c -- A simple diff walker which compares local files against
+ *                 their pristine versions.
  *
  * ====================================================================
  *    Licensed to the Apache Software Foundation (ASF) under one
@@ -89,9 +89,6 @@ struct diff_baton
   /* Should this diff ignore node ancestry? */
   svn_boolean_t ignore_ancestry;
 
-  /* Hash whose keys are const char * changelist names. */
-  apr_hash_t *changelist_hash;
-
   /* Cancel function/baton */
   svn_cancel_func_t cancel_func;
   void *cancel_baton;
@@ -249,11 +246,6 @@ diff_status_callback(void *baton,
   if (eb->cur && eb->cur->skip_children)
     return SVN_NO_ERROR;
 
-  if (eb->changelist_hash != NULL
-      && (!status->changelist
-          || ! svn_hash_gets(eb->changelist_hash, status->changelist)))
-    return SVN_NO_ERROR; /* Filtered via changelist */
-
   /* This code does about the same thing as the inner body of
      walk_local_nodes_diff() in diff_editor.c, except that
      it is already filtered by the status walker, doesn't have to
@@ -358,7 +350,6 @@ diff_status_callback(void *baton,
             SVN_ERR(svn_wc__diff_base_working_diff(db, child_abspath,
                                                    child_relpath,
                                                    SVN_INVALID_REVNUM,
-                                                   eb->changelist_hash,
                                                    eb->processor,
                                                    eb->cur
                                                         ? eb->cur->baton
@@ -402,7 +393,6 @@ diff_status_callback(void *baton,
                                                child_relpath,
                                                eb->processor,
                                                eb->cur ? eb->cur->baton : NULL,
-                                               eb->changelist_hash,
                                                FALSE,
                                                eb->cancel_func,
                                                eb->cancel_baton,
@@ -412,7 +402,6 @@ diff_status_callback(void *baton,
                                               child_relpath, depth_below_here,
                                               eb->processor,
                                               eb->cur ? eb->cur->baton : NULL,
-                                              eb->changelist_hash,
                                               FALSE,
                                               eb->cancel_func,
                                               eb->cancel_baton,
@@ -475,15 +464,23 @@ svn_wc__diff7(const char **root_relpath,
   if (root_is_dir)
     *root_is_dir = (kind == svn_node_dir);
 
+  /* Apply changelist filtering to the output */
+  if (changelist_filter && changelist_filter->nelts)
+    {
+      apr_hash_t *changelist_hash;
+
+      SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelist_filter,
+                                         result_pool));
+      diff_processor = svn_wc__changelist_filter_tree_processor_create(
+                         diff_processor, wc_ctx, local_abspath,
+                         changelist_hash, result_pool);
+    }
+
   eb.db = wc_ctx->db;
   eb.processor = diff_processor;
   eb.ignore_ancestry = ignore_ancestry;
   eb.pool = scratch_pool;
 
-  if (changelist_filter && changelist_filter->nelts)
-    SVN_ERR(svn_hash_from_cstring_keys(&eb.changelist_hash, changelist_filter,
-                                       scratch_pool));
-
   if (ignore_ancestry)
     get_all = TRUE; /* We need unmodified descendants of copies */
   else

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/props.c Wed Sep  3 09:14:58 2014
@@ -62,36 +62,6 @@
 
 #include "svn_private_config.h"
 
-/* Forward declaration.  */
-static svn_error_t *
-prop_conflict_from_skel(const svn_string_t **conflict_desc,
-                        const svn_skel_t *skel,
-                        svn_cancel_func_t cancel_func,
-                        void *cancel_baton,
-                        apr_pool_t *result_pool,
-                        apr_pool_t *scratch_pool);
-
-/* Given a *SINGLE* property conflict in PROP_SKEL, generate a description
-   for it, and write it to STREAM, along with a trailing EOL sequence.
-
-   See prop_conflict_from_skel() for details on PROP_SKEL.  */
-static svn_error_t *
-append_prop_conflict(svn_stream_t *stream,
-                     const svn_skel_t *prop_skel,
-                     svn_cancel_func_t cancel_func,
-                     void *cancel_baton,
-                     apr_pool_t *pool)
-{
-  /* TODO:  someday, perhaps prefix each conflict_description with a
-     timestamp or something? */
-  const svn_string_t *conflict_desc;
-
-  SVN_ERR(prop_conflict_from_skel(&conflict_desc, prop_skel,
-                                  cancel_func, cancel_baton, pool, pool));
-
-  return svn_stream_puts(stream, conflict_desc->data);
-}
-
 /*---------------------------------------------------------------------*/
 
 /*** Merging propchanges into the working copy ***/
@@ -536,29 +506,20 @@ maybe_prop_value(const svn_skel_t *skel,
 }
 
 
-/* Parse a property conflict description from the provided SKEL.
-   The result includes a descriptive message (see generate_conflict_message)
-   and maybe a diff of property values containing conflict markers.
-   The result will be allocated in RESULT_POOL.
-
-   Note: SKEL is a single property conflict of the form:
-
-   ("prop" ([ORIGINAL]) ([MINE]) ([INCOMING]) ([INCOMING_BASE]))
-
-   See notes/wc-ng/conflict-storage for more information.  */
+/* Create a property rejection description for the specified property.
+   The result will be allocated in RESULT_POOL. */
 static svn_error_t *
-prop_conflict_from_skel(const svn_string_t **conflict_desc,
-                        const svn_skel_t *skel,
-                        svn_cancel_func_t cancel_func,
-                        void *cancel_baton,
-                        apr_pool_t *result_pool,
-                        apr_pool_t *scratch_pool)
+prop_conflict_new(const svn_string_t **conflict_desc,
+                  const char *propname,
+                  const svn_string_t *original,
+                  const svn_string_t *mine,
+                  const svn_string_t *incoming,
+                  const svn_string_t *incoming_base,
+                  svn_cancel_func_t cancel_func,
+                  void *cancel_baton,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
 {
-  const svn_string_t *original;
-  const svn_string_t *mine;
-  const svn_string_t *incoming;
-  const svn_string_t *incoming_base;
-  const char *propname;
   svn_diff_t *diff;
   svn_diff_file_options_t *diff_opts;
   svn_stringbuf_t *buf;
@@ -566,17 +527,6 @@ prop_conflict_from_skel(const svn_string
   svn_boolean_t mine_is_binary;
   svn_boolean_t incoming_is_binary;
 
-  /* Navigate to the property name.  */
-  skel = skel->children->next;
-
-  /* We need to copy these into SCRATCH_POOL in order to nul-terminate
-     the values.  */
-  propname = apr_pstrmemdup(scratch_pool, skel->data, skel->len);
-  original = maybe_prop_value(skel->next, scratch_pool);
-  mine = maybe_prop_value(skel->next->next, scratch_pool);
-  incoming = maybe_prop_value(skel->next->next->next, scratch_pool);
-  incoming_base = maybe_prop_value(skel->next->next->next->next, scratch_pool);
-
   buf = generate_conflict_message(propname, original, mine, incoming,
                                   incoming_base, scratch_pool);
 
@@ -703,6 +653,49 @@ prop_conflict_from_skel(const svn_string
   return SVN_NO_ERROR;
 }
 
+/* Parse a property conflict description from the provided SKEL.
+   The result includes a descriptive message (see generate_conflict_message)
+   and maybe a diff of property values containing conflict markers.
+   The result will be allocated in RESULT_POOL.
+
+   Note: SKEL is a single property conflict of the form:
+
+   ("prop" ([ORIGINAL]) ([MINE]) ([INCOMING]) ([INCOMING_BASE]))
+
+   Note: This is not the same format as the property conflicts we store in
+   wc.db since 1.8. This is the legacy format used in the Workqueue in 1.7-1.8 */
+static svn_error_t *
+prop_conflict_from_skel(const svn_string_t **conflict_desc,
+                        const svn_skel_t *skel,
+                        svn_cancel_func_t cancel_func,
+                        void *cancel_baton,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  const svn_string_t *original;
+  const svn_string_t *mine;
+  const svn_string_t *incoming;
+  const svn_string_t *incoming_base;
+  const char *propname;
+
+  /* Navigate to the property name.  */
+  skel = skel->children->next;
+
+  /* We need to copy these into SCRATCH_POOL in order to nul-terminate
+     the values.  */
+  propname = apr_pstrmemdup(scratch_pool, skel->data, skel->len);
+  original = maybe_prop_value(skel->next, scratch_pool);
+  mine = maybe_prop_value(skel->next->next, scratch_pool);
+  incoming = maybe_prop_value(skel->next->next->next, scratch_pool);
+  incoming_base = maybe_prop_value(skel->next->next->next->next, scratch_pool);
+
+  return svn_error_trace(prop_conflict_new(conflict_desc,
+                                           propname,
+                                           original, mine,
+                                           incoming, incoming_base,
+                                           cancel_func, cancel_baton,
+                                           result_pool, scratch_pool));
+}
 
 /* Create a property conflict file at PREJFILE based on the property
    conflicts in CONFLICT_SKEL.  */
@@ -710,7 +703,7 @@ svn_error_t *
 svn_wc__create_prejfile(const char **tmp_prejfile_abspath,
                         svn_wc__db_t *db,
                         const char *local_abspath,
-                        const svn_skel_t *conflict_skel,
+                        const svn_skel_t *prop_conflict_data,
                         svn_cancel_func_t cancel_func,
                         void *cancel_baton,
                         apr_pool_t *result_pool,
@@ -730,12 +723,87 @@ svn_wc__create_prejfile(const char **tmp
                                  tempdir_abspath, svn_io_file_del_none,
                                  scratch_pool, iterpool));
 
-  for (scan = conflict_skel->children->next; scan != NULL; scan = scan->next)
+  if (prop_conflict_data)
     {
-      svn_pool_clear(iterpool);
+      for (scan = prop_conflict_data->children->next;
+            scan != NULL; scan = scan->next)
+        {
+          const svn_string_t *conflict_desc;
+
+          svn_pool_clear(iterpool);
+
+          SVN_ERR(prop_conflict_from_skel(&conflict_desc, scan,
+                                          cancel_func, cancel_baton,
+                                          iterpool, iterpool));
 
-      SVN_ERR(append_prop_conflict(stream, scan, cancel_func, cancel_baton,
-                                   iterpool));
+          SVN_ERR(svn_stream_puts(stream, conflict_desc->data));
+        }
+    }
+  else
+    {
+      svn_wc_operation_t operation;
+      apr_hash_index_t *hi;
+      apr_hash_t *old_props;
+      apr_hash_t *mine_props;
+      apr_hash_t *their_original_props;
+      apr_hash_t *their_props;
+      apr_hash_t *conflicted_props;
+      svn_skel_t *conflicts;
+
+      SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath,
+                                      scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, NULL,
+                                         db, local_abspath,
+                                         conflicts,
+                                         scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__conflict_read_prop_conflict(NULL,
+                                                  &mine_props,
+                                                  &their_original_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_original_props;
+
+      /* ### TODO: Sort conflicts? */
+      for (hi = apr_hash_first(scratch_pool, conflicted_props);
+           hi;
+           hi = apr_hash_next(hi))
+        {
+          const svn_string_t *conflict_desc;
+          const char *propname = apr_hash_this_key(hi);
+          const svn_string_t *old_value;
+          const svn_string_t *mine_value;
+          const svn_string_t *their_value;
+          const svn_string_t *their_original_value;
+
+          svn_pool_clear(iterpool);
+
+          old_value = old_props ? svn_hash_gets(old_props, propname) : NULL;
+          mine_value = mine_props ? svn_hash_gets(mine_props, propname) : NULL;
+          their_value = their_props ? svn_hash_gets(their_props, propname)
+                                    : NULL;
+          their_original_value = their_original_props
+                                    ? svn_hash_gets(their_original_props, propname)
+                                    : NULL;
+
+          SVN_ERR(prop_conflict_new(&conflict_desc,
+                                    propname, old_value, mine_value,
+                                    their_value, their_original_value,
+                                    cancel_func, cancel_baton,
+                                    iterpool, iterpool));
+
+          SVN_ERR(svn_stream_puts(stream, conflict_desc->data));
+        }
     }
 
   SVN_ERR(svn_stream_close(stream));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/props.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/props.h?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/props.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/props.h Wed Sep  3 09:14:58 2014
@@ -139,11 +139,15 @@ svn_wc__get_actual_props(apr_hash_t **pr
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool);
 
+/* Creates a property reject file at *TMP_PREJFILE_ABSPATH, with
+   either the property conflict data from DB (when PROP_CONFLICT_DATA
+   is NULL) or the information in PROP_CONFLICT_DATA if it isn't.
+ */
 svn_error_t *
 svn_wc__create_prejfile(const char **tmp_prejfile_abspath,
                         svn_wc__db_t *db,
                         const char *local_abspath,
-                        const svn_skel_t *conflict_skel,
+                        const svn_skel_t *prop_conflict_data,
                         svn_cancel_func_t cancel_func,
                         void *cancel_baton,
                         apr_pool_t *result_pool,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/tree_conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/tree_conflicts.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/tree_conflicts.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/tree_conflicts.c Wed Sep  3 09:14:58 2014
@@ -46,6 +46,7 @@ static const svn_token_map_t node_kind_m
   { "file", svn_node_file },
   { "dir",  svn_node_dir },
   { "",     svn_node_unknown },
+  /* ### should also map svn_node_symlink */
   { NULL }
 };
 

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/update_editor.c Wed Sep  3 09:14:58 2014
@@ -1133,17 +1133,6 @@ set_target_revision(void *edit_baton,
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-check_tree_conflict(svn_skel_t **pconflict,
-                    struct edit_baton *eb,
-                    const char *local_abspath,
-                    svn_wc__db_status_t working_status,
-                    svn_boolean_t exists_in_repos,
-                    svn_node_kind_t expected_kind,
-                    svn_wc_conflict_action_t action,
-                    apr_pool_t *result_pool,
-                    apr_pool_t *scratch_pool);
-
 /* An svn_delta_editor_t function. */
 static svn_error_t *
 open_root(void *edit_baton,
@@ -2995,6 +2984,7 @@ absent_node(const char *path,
   svn_error_t *err;
   svn_wc__db_status_t status;
   svn_node_kind_t kind;
+  svn_skel_t *tree_conflict = NULL;
 
   if (pb->skip_this)
     return SVN_NO_ERROR;
@@ -3083,25 +3073,28 @@ absent_node(const char *path,
     {
       /* We have a local addition. If this would be a BASE node it would have
          been deleted before we get here. (Which might have turned it into
-         a copy).
-
-         ### This should be recorded as a tree conflict and the update
-         ### can just continue, as we can just record the absent status
-         ### in BASE.
-       */
+         a copy). */
       SVN_ERR_ASSERT(status != svn_wc__db_status_normal);
 
-      return svn_error_createf(
-         SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-         _("Failed to mark '%s' absent: item of the same name is already "
-           "scheduled for addition"),
-         svn_dirent_local_style(local_abspath, pool));
+      if (!pb->shadowed && !pb->edit_obstructed)
+        SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
+                                    status, FALSE, svn_node_unknown,
+                                    svn_wc_conflict_action_add,
+                                    scratch_pool, scratch_pool));
+
     }
 
   {
     const char *repos_relpath;
     repos_relpath = svn_relpath_join(pb->new_repos_relpath, name, scratch_pool);
 
+    if (tree_conflict)
+      SVN_ERR(complete_conflict(tree_conflict, eb, local_abspath,
+                                NULL, SVN_INVALID_REVNUM, repos_relpath,
+                                kind, svn_node_unknown,
+                                scratch_pool, scratch_pool));
+                                
+
     /* Insert an excluded node below the parent node to note that this child
        is absent. (This puts it in the parent db if the child is obstructed) */
     SVN_ERR(svn_wc__db_base_add_excluded_node(eb->db, local_abspath,
@@ -3110,8 +3103,23 @@ absent_node(const char *path,
                                               *(eb->target_revision),
                                               absent_kind,
                                               svn_wc__db_status_server_excluded,
-                                              NULL, NULL,
+                                              tree_conflict, NULL,
                                               scratch_pool));
+
+    if (tree_conflict)
+      {
+        if (eb->conflict_func)
+          SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, local_abspath,
+                                                   tree_conflict,
+                                                   NULL /* merge_options */,
+                                                   eb->conflict_func,
+                                                   eb->conflict_baton,
+                                                   eb->cancel_func,
+                                                   eb->cancel_baton,
+                                                   scratch_pool));
+        do_notification(eb, local_abspath, kind, svn_wc_notify_tree_conflict,
+                        scratch_pool);
+      }
   }
 
   svn_pool_destroy(scratch_pool);

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db.h?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/wc_db.h Wed Sep  3 09:14:58 2014
@@ -2138,16 +2138,16 @@ svn_wc__db_read_props_streamily(svn_wc__
                                 apr_pool_t *scratch_pool);
 
 
-/* Set *PROPS to the properties of the node LOCAL_ABSPATH in the WORKING
-   tree (looking through to the BASE tree as required).
-
-   ### *PROPS will set set to NULL in the following situations:
-   ### ... tbd.  see props.c:svn_wc__get_pristine_props()
+/* Set *PROPS to the base properties of the node at LOCAL_ABSPATH.
 
    *PROPS maps "const char *" names to "const svn_string_t *" values.
    If the node has no properties, set *PROPS to an empty hash.
-   If the node is not present, return an error.
+   If the base node is in a state that cannot have properties (such as
+   not-present or locally added without copy-from), return an error.
+
    Allocate *PROPS and its keys and values in RESULT_POOL.
+
+   See also svn_wc_get_pristine_props().
 */
 svn_error_t *
 svn_wc__db_read_pristine_props(apr_hash_t **props,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/workqueue.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/workqueue.c Wed Sep  3 09:14:58 2014
@@ -1086,70 +1086,6 @@ svn_wc__wq_build_sync_file_flags(svn_ske
 
 /* OP_PREJ_INSTALL  */
 
-/* Helper for run_prej_install.  Originally in conflict.c */
-static svn_skel_t *
-prop_conflict_skel_new(apr_pool_t *result_pool)
-{
-  svn_skel_t *operation = svn_skel__make_empty_list(result_pool);
-  svn_skel_t *result = svn_skel__make_empty_list(result_pool);
-
-  svn_skel__prepend(operation, result);
-  return result;
-}
-
-/* Helper for prop_conflict_skel_add.  Originally in conflict.c */
-static void
-prepend_prop_value(const svn_string_t *value,
-                   svn_skel_t *skel,
-                   apr_pool_t *result_pool)
-{
-  svn_skel_t *value_skel = svn_skel__make_empty_list(result_pool);
-
-  if (value != NULL)
-    {
-      const void *dup = apr_pmemdup(result_pool, value->data, value->len);
-
-      svn_skel__prepend(svn_skel__mem_atom(dup, value->len, result_pool),
-                        value_skel);
-    }
-
-  svn_skel__prepend(value_skel, skel);
-}
-
-
-/* Helper for run_prej_install.  Originally in conflict.c */
-static svn_error_t *
-prop_conflict_skel_add(
-  svn_skel_t *skel,
-  const char *prop_name,
-  const svn_string_t *original_value,
-  const svn_string_t *mine_value,
-  const svn_string_t *incoming_value,
-  const svn_string_t *incoming_base_value,
-  apr_pool_t *result_pool,
-  apr_pool_t *scratch_pool)
-{
-  svn_skel_t *prop_skel = svn_skel__make_empty_list(result_pool);
-
-  /* ### check that OPERATION has been filled in.  */
-
-  /* See notes/wc-ng/conflict-storage  */
-  prepend_prop_value(incoming_base_value, prop_skel, result_pool);
-  prepend_prop_value(incoming_value, prop_skel, result_pool);
-  prepend_prop_value(mine_value, prop_skel, result_pool);
-  prepend_prop_value(original_value, prop_skel, result_pool);
-  svn_skel__prepend_str(apr_pstrdup(result_pool, prop_name), prop_skel,
-                        result_pool);
-  svn_skel__prepend_str(SVN_WC__CONFLICT_KIND_PROP, prop_skel, result_pool);
-
-  /* Now we append PROP_SKEL to the end of the provided conflict SKEL.  */
-  svn_skel__append(skel, prop_skel);
-
-  return SVN_NO_ERROR;
-}
-
-
-
 static svn_error_t *
 run_prej_install(work_item_baton_t *wqb,
                  svn_wc__db_t *db,
@@ -1182,62 +1118,7 @@ run_prej_install(work_item_baton_t *wqb,
   if (arg1->next != NULL)
     prop_conflict_skel = arg1->next; /* Before Subversion 1.9 */
   else
-    {
-      svn_wc_operation_t operation;
-      apr_hash_index_t *hi;
-      apr_hash_t *old_props;
-      apr_hash_t *mine_props;
-      apr_hash_t *their_original_props;
-      apr_hash_t *their_props;
-      apr_hash_t *conflicted_props;
-
-      SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, NULL,
-                                         db, local_abspath,
-                                         conflicts,
-                                         scratch_pool, scratch_pool));
-
-      /* Create the data in the skel in the same format used as 1.7 */
-      SVN_ERR(svn_wc__conflict_read_prop_conflict(NULL,
-                                                  &mine_props,
-                                                  &their_original_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_original_props;
-
-      prop_conflict_skel = prop_conflict_skel_new(scratch_pool);
-
-      for (hi = apr_hash_first(scratch_pool, conflicted_props);
-           hi;
-           hi = apr_hash_next(hi))
-        {
-          const char *propname = apr_hash_this_key(hi);
-
-          SVN_ERR(prop_conflict_skel_add(
-                          prop_conflict_skel, propname,
-                          old_props
-                                  ? svn_hash_gets(old_props, propname)
-                                  : NULL,
-                          mine_props
-                                  ? svn_hash_gets(mine_props, propname)
-                                  : NULL,
-                          their_props
-                                  ? svn_hash_gets(their_props, propname)
-                                    : NULL,
-                          their_original_props
-                                  ? svn_hash_gets(their_original_props, propname)
-                                    : NULL,
-                          scratch_pool, scratch_pool));
-        }
-    }
+    prop_conflict_skel = NULL; /* Read from DB */
 
   /* Construct a property reject file in the temporary area.  */
   SVN_ERR(svn_wc__create_prejfile(&tmp_prejfile_abspath,

Propchange: subversion/branches/move-tracking-2/subversion/mod_dav_svn/status.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/branches/move-tracking-2/subversion/svn/cl-conflicts.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svn/cl-conflicts.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svn/cl-conflicts.c (original)
+++ subversion/branches/move-tracking-2/subversion/svn/cl-conflicts.c Wed Sep  3 09:14:58 2014
@@ -75,6 +75,7 @@ local_reason_str(svn_node_kind_t kind, s
   switch (kind)
     {
       case svn_node_file:
+      case svn_node_symlink:
         switch (reason)
           {
           case svn_wc_conflict_reason_edited:
@@ -126,9 +127,32 @@ local_reason_str(svn_node_kind_t kind, s
             return _("local dir moved here");
           }
         break;
-      case svn_node_symlink:
       case svn_node_none:
       case svn_node_unknown:
+        switch (reason)
+          {
+          case svn_wc_conflict_reason_edited:
+            return _("local edit");
+          case svn_wc_conflict_reason_obstructed:
+            return _("local obstruction");
+          case svn_wc_conflict_reason_deleted:
+            return _("local delete");
+          case svn_wc_conflict_reason_missing:
+            if (operation == svn_wc_operation_merge)
+              return _("local missing or deleted or moved away");
+            else
+              return _("local missing");
+          case svn_wc_conflict_reason_unversioned:
+            return _("local unversioned");
+          case svn_wc_conflict_reason_added:
+            return _("local add");
+          case svn_wc_conflict_reason_replaced:
+            return _("local replace");
+          case svn_wc_conflict_reason_moved_away:
+            return _("local moved away");
+          case svn_wc_conflict_reason_moved_here:
+            return _("local moved here");
+          }
         break;
     }
   return NULL;
@@ -142,6 +166,7 @@ incoming_action_str(svn_node_kind_t kind
   switch (kind)
     {
       case svn_node_file:
+      case svn_node_symlink:
         switch (action)
           {
             case svn_wc_conflict_action_edit:
@@ -151,7 +176,7 @@ incoming_action_str(svn_node_kind_t kind
             case svn_wc_conflict_action_delete:
               return _("incoming file delete or move");
             case svn_wc_conflict_action_replace:
-              return _("incoming file replace");
+              return _("incoming replace with file");
           }
         break;
       case svn_node_dir:
@@ -164,12 +189,22 @@ incoming_action_str(svn_node_kind_t kind
             case svn_wc_conflict_action_delete:
               return _("incoming dir delete or move");
             case svn_wc_conflict_action_replace:
-              return _("incoming dir replace");
+              return _("incoming replace with dir");
           }
         break;
-      case svn_node_symlink:
       case svn_node_none:
       case svn_node_unknown:
+        switch (action)
+          {
+            case svn_wc_conflict_action_edit:
+              return _("incoming edit");
+            case svn_wc_conflict_action_add:
+              return _("incoming add");
+            case svn_wc_conflict_action_delete:
+              return _("incoming delete or move");
+            case svn_wc_conflict_action_replace:
+              return _("incoming replace");
+          }
         break;
     }
   return NULL;

Modified: subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c Wed Sep  3 09:14:58 2014
@@ -487,25 +487,6 @@ static const resolver_option_t prop_conf
   { NULL }
 };
 
-/* Resolver options for an obstructued addition */
-static const resolver_option_t obstructed_add_options[] =
-{
-  { "mf", N_("my version"),       N_("accept pre-existing item (ignore "
-                                     "upstream addition)  [mine-full]"),
-                                  svn_wc_conflict_choose_mine_full },
-  { "tf", N_("their version"),    N_("accept incoming item (overwrite "
-                                     "pre-existing item)  [theirs-full]"),
-                                  svn_wc_conflict_choose_theirs_full },
-  { "p",  N_("postpone"),         N_("mark the conflict to be resolved later"
-                                     "  [postpone]"),
-                                  svn_wc_conflict_choose_postpone },
-  { "q",  N_("quit resolution"),  N_("postpone all remaining conflicts"),
-                                  svn_wc_conflict_choose_postpone },
-  { "h",  N_("help"),             N_("show this help (also '?')"),
-                                  svn_wc_conflict_choose_undefined },
-  { NULL }
-};
-
 /* Resolver options for a tree conflict */
 static const resolver_option_t tree_conflict_options[] =
 {
@@ -1148,56 +1129,6 @@ handle_tree_conflict(svn_wc_conflict_res
   return SVN_NO_ERROR;
 }
 
-/* Ask the user what to do about the obstructed add described by DESC.
- * Return the answer in RESULT. B is the conflict baton for this
- * conflict resolution session.
- * SCRATCH_POOL is used for temporary allocations. */
-static svn_error_t *
-handle_obstructed_add(svn_wc_conflict_result_t *result,
-                      const svn_wc_conflict_description2_t *desc,
-                      svn_cl__interactive_conflict_baton_t *b,
-                      apr_pool_t *scratch_pool)
-{
-  apr_pool_t *iterpool;
-
-  SVN_ERR(svn_cmdline_fprintf(
-               stderr, scratch_pool,
-               _("Conflict discovered when trying to add '%s'.\n"
-                 "An object of the same name already exists.\n"),
-               svn_cl__local_style_skip_ancestor(b->path_prefix,
-                                                 desc->local_abspath,
-                                                 scratch_pool)));
-
-  iterpool = svn_pool_create(scratch_pool);
-  while (1)
-    {
-      const resolver_option_t *opt;
-
-      svn_pool_clear(iterpool);
-
-      SVN_ERR(prompt_user(&opt, obstructed_add_options, NULL, b->pb,
-                          iterpool));
-      if (! opt)
-        continue;
-
-      if (strcmp(opt->code, "q") == 0)
-        {
-          result->choice = opt->choice;
-          b->accept_which = svn_cl__accept_postpone;
-          b->quit = TRUE;
-          break;
-        }
-      else if (opt->choice != svn_wc_conflict_choose_undefined)
-        {
-          result->choice = opt->choice;
-          break;
-        }
-    }
-  svn_pool_destroy(iterpool);
-
-  return SVN_NO_ERROR;
-}
-
 /* The body of svn_cl__conflict_func_interactive(). */
 static svn_error_t *
 conflict_func_interactive(svn_wc_conflict_result_t **result,
@@ -1341,29 +1272,6 @@ conflict_func_interactive(svn_wc_conflic
     SVN_ERR(handle_text_conflict(*result, desc, b, scratch_pool));
   else if (desc->kind == svn_wc_conflict_kind_property)
     SVN_ERR(handle_prop_conflict(*result, desc, b, result_pool, scratch_pool));
-
-  /*
-    Dealing with obstruction of additions can be tricky.  The
-    obstructing item could be unversioned, versioned, or even
-    schedule-add.  Here's a matrix of how the caller should behave,
-    based on results we return.
-
-                         Unversioned       Versioned       Schedule-Add
-
-      choose_mine       skip addition,    skip addition     skip addition
-                        add existing item
-
-      choose_theirs     destroy file,    schedule-delete,   revert add,
-                        add new item.    add new item.      rm file,
-                                                            add new item
-
-      postpone               [              bail out                 ]
-
-   */
-  else if ((desc->action == svn_wc_conflict_action_add)
-           && (desc->reason == svn_wc_conflict_reason_obstructed))
-    SVN_ERR(handle_obstructed_add(*result, desc, b, scratch_pool));
-
   else if (desc->kind == svn_wc_conflict_kind_tree)
     SVN_ERR(handle_tree_conflict(*result, desc, b, scratch_pool));
 

Modified: subversion/branches/move-tracking-2/subversion/svnfsfs/dump-index-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnfsfs/dump-index-cmd.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnfsfs/dump-index-cmd.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnfsfs/dump-index-cmd.c Wed Sep  3 09:14:58 2014
@@ -61,14 +61,12 @@ dump_index(const char *path,
 {
   svn_fs_fs__revision_file_t *rev_file;
   svn_fs_t *fs;
-  fs_fs_data_t *ffd;
   int i;
   apr_off_t offset, max_offset;
   apr_pool_t *iterpool = svn_pool_create(pool);
 
   /* Check repository type and open it. */
   SVN_ERR(open_fs(&fs, path, pool));
-  ffd = fs->fsap_data;
 
   /* Check the FS format. */
   if (! svn_fs_fs__use_log_addressing(fs, revision))
@@ -94,7 +92,7 @@ dump_index(const char *path,
        * we start at the first offset not covered. */
       svn_pool_clear(iterpool);
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs, rev_file, revision,
-                                          offset, ffd->p2l_page_size,
+                                          offset, INDEX_BLOCK_SIZE,
                                           iterpool));
 
       /* Print entries for this block, one line per entry. */
@@ -110,7 +108,7 @@ dump_index(const char *path,
           offset = entry->offset + entry->size;
 
           printf("%12" APR_UINT64_T_HEX_FMT " %12" APR_UINT64_T_HEX_FMT
-                 " %s %9ld %8" APR_UINT64_T_HEX_FMT " %s\n",
+                 " %s %9ld %8" APR_UINT64_T_FMT " %s\n",
                  (apr_uint64_t)entry->offset, (apr_uint64_t)entry->size,
                  type_str, entry->item.revision, entry->item.number,
                  fnv1_to_string(entry->fnv1_checksum, iterpool));

Modified: subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnfsfs/stats-cmd.c Wed Sep  3 09:14:58 2014
@@ -33,6 +33,7 @@
 #include "../libsvn_fs_fs/pack.h"
 #include "../libsvn_fs_fs/rev_file.h"
 #include "../libsvn_fs_fs/util.h"
+#include "../libsvn_fs_fs/fs_fs.h"
 #include "../libsvn_fs/fs-loader.h"
 
 #include "svn_private_config.h"
@@ -225,6 +226,15 @@ typedef struct fs_t
   /* FS API object*/
   svn_fs_t *fs;
 
+  /* The HEAD revision. */
+  svn_revnum_t head;
+
+  /* Number of revs per shard; 0 for non-sharded repos. */
+  int shard_size;
+
+  /* First non-packed revision. */
+  svn_revnum_t min_unpacked_rev;
+
   /* all revisions */
   apr_array_header_t *revisions;
 
@@ -603,17 +613,16 @@ read_revision_header(apr_size_t *changes
 static svn_error_t *
 fs_open(fs_t **fs, const char *path, apr_pool_t *pool)
 {
-  fs_fs_data_t *ffd;
-
   *fs = apr_pcalloc(pool, sizeof(**fs));
 
   /* Check repository type and open it. */
   SVN_ERR(open_fs(&(*fs)->fs, path, pool));
 
-  /* Check the FS format number. */
-  ffd = (*fs)->fs->fsap_data;
-  if ((ffd->format != 4) && (ffd->format != 6) && (ffd->format != 7))
-    return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL, NULL);
+  /* Read repository dimensions. */
+  (*fs)->shard_size = svn_fs_fs__shard_size((*fs)->fs);
+  SVN_ERR(svn_fs_fs__youngest_rev(&(*fs)->head, (*fs)->fs, pool));
+  SVN_ERR(svn_fs_fs__min_unpacked_rev(&(*fs)->min_unpacked_rev, (*fs)->fs,
+                                      pool));
 
   return SVN_NO_ERROR;
 }
@@ -1232,13 +1241,12 @@ read_phys_pack_file(fs_t *fs,
   int i;
   apr_off_t file_size = 0;
   apr_file_t *file;
-  fs_fs_data_t *ffd = fs->fs->fsap_data;
 
   SVN_ERR(open_rev_or_pack_file(&file, fs, base, local_pool));
   SVN_ERR(get_file_size(&file_size, file, local_pool));
 
   /* process each revision in the pack file */
-  for (i = 0; i < ffd->max_files_per_dir; ++i)
+  for (i = 0; i < fs->shard_size; ++i)
     {
       apr_size_t root_node_offset;
       svn_stringbuf_t *rev_content;
@@ -1250,7 +1258,7 @@ read_phys_pack_file(fs_t *fs,
       info->revision = base + i;
       SVN_ERR(svn_fs_fs__get_packed_offset(&info->offset, fs->fs, base + i,
                                            iter_pool));
-      if (i + 1 == ffd->max_files_per_dir)
+      if (i + 1 == fs->shard_size)
         SVN_ERR(svn_io_file_seek(file, APR_END, &info->end, iter_pool));
       else
         SVN_ERR(svn_fs_fs__get_packed_offset(&info->end, fs->fs,
@@ -1301,7 +1309,6 @@ read_phys_revision_file(fs_t *fs,
   revision_info_t *info = apr_pcalloc(pool, sizeof(*info));
   apr_off_t file_size = 0;
   apr_file_t *file;
-  fs_fs_data_t *ffd = fs->fs->fsap_data;
 
   /* read the whole pack file into memory */
   SVN_ERR(open_rev_or_pack_file(&file, fs, revision, local_pool));
@@ -1336,7 +1343,9 @@ read_phys_revision_file(fs_t *fs,
                        pool, local_pool));
 
   /* show progress every 1000 revs or so */
-  if (revision % ffd->max_files_per_dir == 0)
+  if (fs->shard_size && (revision % fs->shard_size == 0))
+    print_progress(revision);
+  if (!fs->shard_size && (revision % 1000 == 0))
     print_progress(revision);
 
   svn_pool_destroy(local_pool);
@@ -1354,13 +1363,11 @@ read_item(svn_stringbuf_t **contents,
           svn_fs_fs__p2l_entry_t *entry,
           apr_pool_t *pool)
 {
-  fs_fs_data_t *ffd = fs->fs->fsap_data;
-
   svn_stringbuf_t *item = svn_stringbuf_create_ensure(entry->size, pool);
   item->len = entry->size;
   item->data[item->len] = 0;
 
-  SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size, NULL,
+  SVN_ERR(svn_io_file_aligned_seek(rev_file->file, REV_FILE_BLOCK_SIZE, NULL,
                                    entry->offset, pool));
   SVN_ERR(svn_io_file_read_full2(rev_file->file, item->data, item->len,
                                  NULL, NULL, pool));
@@ -1385,7 +1392,6 @@ read_log_rev_or_packfile(fs_t *fs,
   apr_off_t offset = 0;
   int i;
   svn_fs_fs__revision_file_t *rev_file;
-  fs_fs_data_t *ffd = fs->fs->fsap_data;
 
   /* we will process every revision in the rev / pack file */
   for (i = 0; i < count; ++i)
@@ -1418,7 +1424,7 @@ read_log_rev_or_packfile(fs_t *fs,
 
       /* get all entries for the current block */
       SVN_ERR(svn_fs_fs__p2l_index_lookup(&entries, fs->fs, rev_file, base,
-                                          offset, ffd->p2l_page_size,
+                                          offset, INDEX_BLOCK_SIZE,
                                           iterpool));
 
       /* process all entries (and later continue with the next block) */
@@ -1477,8 +1483,7 @@ read_log_pack_file(fs_t *fs,
                    svn_revnum_t base,
                    apr_pool_t *pool)
 {
-  fs_fs_data_t *ffd = fs->fs->fsap_data;
-  SVN_ERR(read_log_rev_or_packfile(fs, base, ffd->max_files_per_dir, pool));
+  SVN_ERR(read_log_rev_or_packfile(fs, base, fs->shard_size, pool));
 
   /* one more pack file processed */
   print_progress(base);
@@ -1494,11 +1499,12 @@ read_log_revision_file(fs_t *fs,
                        svn_revnum_t revision,
                        apr_pool_t *pool)
 {
-  fs_fs_data_t *ffd = fs->fs->fsap_data;
   SVN_ERR(read_log_rev_or_packfile(fs, revision, 1, pool));
 
   /* show progress every 1000 revs or so */
-  if (revision % ffd->max_files_per_dir == 0)
+  if (fs->shard_size && (revision % fs->shard_size == 0))
+    print_progress(revision);
+  if (!fs->shard_size && (revision % 1000 == 0))
     print_progress(revision);
 
   return SVN_NO_ERROR;
@@ -1513,11 +1519,9 @@ read_revisions(fs_t **fs,
                apr_pool_t *pool)
 {
   svn_revnum_t revision;
-  fs_fs_data_t *ffd;
 
   /* determine cache sizes */
   SVN_ERR(fs_open(fs, path, pool));
-  ffd = (*fs)->fs->fsap_data;
 
   /* create data containers and caches
    * Note: this assumes that int is at least 32-bits and that we only support
@@ -1525,8 +1529,7 @@ read_revisions(fs_t **fs,
    * of both the nelts field of the array and our revision numbers). This
    * means this code will fail on platforms where int is less than 32-bits
    * and the repository has more revisions than int can hold. */
-  (*fs)->revisions = apr_array_make(pool,
-                                    (int) ffd->youngest_rev_cache + 1,
+  (*fs)->revisions = apr_array_make(pool, (int) (*fs)->head + 1,
                                     sizeof(revision_info_t *));
   (*fs)->null_base = apr_pcalloc(pool, sizeof(*(*fs)->null_base));
   initialize_largest_changes(*fs, 64, pool);
@@ -1542,15 +1545,15 @@ read_revisions(fs_t **fs,
 
   /* read all packed revs */
   for ( revision = 0
-      ; revision < ffd->min_unpacked_rev
-      ; revision += ffd->max_files_per_dir)
+      ; revision < (*fs)->min_unpacked_rev
+      ; revision += (*fs)->shard_size)
     if (svn_fs_fs__use_log_addressing((*fs)->fs, revision))
       SVN_ERR(read_log_pack_file(*fs, revision, pool));
     else
       SVN_ERR(read_phys_pack_file(*fs, revision, pool));
 
   /* read non-packed revs */
-  for ( ; revision <= ffd->youngest_rev_cache; ++revision)
+  for ( ; revision <= (*fs)->head; ++revision)
     if (svn_fs_fs__use_log_addressing((*fs)->fs, revision))
       SVN_ERR(read_log_revision_file(*fs, revision, pool));
     else

Modified: subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.c?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.c Wed Sep  3 09:14:58 2014
@@ -149,13 +149,37 @@ static const svn_opt_subcommand_desc2_t 
    {0} },
 
   {"dump-index", subcommand__dump_index, {0}, N_
-   ("usage: svnfsfs dump-index REPOS_PATH\n\n"
-    "Dump the index contents to console.\n"),
+   ("usage: svnfsfs dump-index REPOS_PATH -r REV\n\n"
+    "Dump the index contents for the revision / pack file containing revision REV\n"
+    "to console.  This is only available for FSFS format 7 (SVN 1.9+) repositories.\n"
+    "The table produced contains a header in the first line followed by one line\n"
+    "per index entry, ordered by location in the revision / pack file.  Columns:\n\n"
+    "   * Byte offset (hex) at which the item starts\n"
+    "   * Length (hex) of the item in bytes\n"
+    "   * Item type (string) is one of the following:\n\n"
+    "        none ... Unused section.  File contents shall be NULs.\n"
+    "        frep ... File representation.\n"
+    "        drep ... Directory representation.\n"
+    "        fprop .. File property.\n"
+    "        dprop .. Directory property.\n"
+    "        node ... Node revision.\n"
+    "        chgs ... Changed paths list.\n"
+    "        rep .... Representation of unknown type.  Should not be used.\n"
+    "        ??? .... Invalid.  Index data is corrupt.\n\n"
+    "        The distinction between frep, drep, fprop and dprop is a mere internal\n"
+    "        classification used for various optimizations and does not affect the\n"
+    "        operational correctness.\n\n"
+    "   * Revision that the item belongs to (decimal)\n"
+    "   * Item number (decimal) within that revision\n"
+    "   * Modified FNV1a checksum (8 hex digits)\n"),
    {'r', 'M'} },
 
   {"load-index", subcommand__load_index, {0}, N_
    ("usage: svnfsfs load-index REPOS_PATH\n\n"
-    "Read the index contents to console.\n"),
+    "Read the index contents to console.  The format is the same as produced by the\n"
+    "dump command, except that checksum as well as header are optional and will be\n"
+    "ignored.  The data must cover the full revision / pack file;  the revision\n"
+    "number is automatically extracted from input stream.  No ordering is required.\n"),
    {'M'} },
 
   {"stats", subcommand__stats, {0}, N_

Modified: subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.h?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.h (original)
+++ subversion/branches/move-tracking-2/subversion/svnfsfs/svnfsfs.h Wed Sep  3 09:14:58 2014
@@ -54,6 +54,19 @@ svn_opt_subcommand_t
   subcommand__load_index,
   subcommand__stats;
 
+
+/* We read rev / pack files in blocks of this size.
+ * Within reason, any positive value is possible with smaller values
+ * increasing the OS chatter and larger values needlessly reading
+ * file contents we won't need. */
+#define REV_FILE_BLOCK_SIZE 0x10000
+
+/* We request P2L index information (i.e. contents descriptions) for
+ * rev / pack files blocks of this size.  Within reason, any positive
+ * value is possible with smaller values increasing the cache lookup
+ * overhead.  A good default is the fsfs.conf default of 1MB. */
+#define INDEX_BLOCK_SIZE 0x100000
+
 /* Check that the filesystem at PATH is an FSFS repository and then open it.
  * Return the filesystem in *FS, allocated in POOL. */
 svn_error_t *

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/authz_tests.py?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/authz_tests.py Wed Sep  3 09:14:58 2014
@@ -1253,17 +1253,17 @@ def authz_tree_conflict(sbox):
   # And now create an obstruction
   sbox.simple_mkdir('A/C')
 
-  expected_output = svntest.wc.State(wc_dir, {})
-  expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
-  expected_status.tweak('A/C', status='A ', wc_rev='0')
-  expected_status.tweak('A', '', status='! ', wc_rev='1')
+  expected_output = svntest.wc.State(wc_dir, {
+      'A/C' : Item(status='  ', treeconflict='C'),
+      })
+  expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+  expected_status.tweak('A/C', status='R ', treeconflict='C')
 
   svntest.actions.run_and_verify_update(wc_dir,
                                         expected_output,
                                         None,
                                         expected_status,
-                                        "Failed to mark '.*C' (server|absent):",
-                                        None, None, None, None, 0,
+                                        None, None, None, None, None, 0,
                                         '-r', '1', wc_dir)
 
 @Issue(3900)

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py?rev=1622195&r1=1622194&r2=1622195&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/diff_tests.py Wed Sep  3 09:14:58 2014
@@ -3215,7 +3215,7 @@ def diff_git_format_wc_wc(sbox):
 
   expected_output = make_git_diff_header(
                          alpha_copied_path, "A/B/E/alpha_copied",
-                         "nonexistent", "working copy",
+                         "revision 1", "working copy",
                          copyfrom_path="A/B/E/alpha",
                          copyfrom_rev='1', cp=True,
                          text_changes=True) + [
@@ -4782,6 +4782,50 @@ def diff_replaced_moved(sbox):
   svntest.actions.run_and_verify_svn(None, None, [],
                                      'diff', sbox.ospath('AA/B'), '-r1')
 
+# Regression test for the fix in r1619380. Prior to this (and in releases
+# 1.8.0 through 1.8.10) a local diff incorrectly showed a copied dir's
+# properties as added, whereas it should show only the changes against the
+# copy-source.
+def diff_local_copied_dir(sbox):
+  "local WC diff of copied dir"
+
+  sbox.build()
+
+  was_cwd = os.getcwd()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = ''
+
+  try:
+    sbox.simple_propset('p1', 'v1', 'A/C')
+    sbox.simple_commit()
+
+    # dir with no prop changes
+    sbox.simple_copy('A/C', 'C2')
+    # dir with prop changes
+    sbox.simple_copy('A/C', 'C3')
+    sbox.simple_propset('p2', 'v2', 'C3')
+
+    expected_output_C2 = []
+    expected_output_C3 = [
+      'Index: C3\n',
+      '===================================================================\n',
+      '--- C3	(revision 2)\n',
+      '+++ C3	(working copy)\n',
+      '\n',
+      'Property changes on: C3\n',
+      '___________________________________________________________________\n',
+      'Added: p2\n',
+      '## -0,0 +1 ##\n',
+      '+v2\n',
+      '\ No newline at end of property\n',
+    ]
+
+    svntest.actions.run_and_verify_svn(None, expected_output_C2, [],
+                                       'diff', 'C2')
+    svntest.actions.run_and_verify_svn(None, expected_output_C3, [],
+                                       'diff', 'C3')
+  finally:
+    os.chdir(was_cwd)
 
 
 ########################################################################
@@ -4873,6 +4917,7 @@ test_list = [ None,
               diff_parent_dir,
               diff_deleted_in_move_against_repos,
               diff_replaced_moved,
+              diff_local_copied_dir,
               ]
 
 if __name__ == '__main__':