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 2010/09/15 21:32:38 UTC

svn commit: r997472 [22/41] - in /subversion/branches/py-tests-as-modules: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/server-side/ notes/ notes/tree-conflicts/ notes/wc-ng/ subversion/bindings/javahl/native/ subversi...

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/merge.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/merge.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/merge.c Wed Sep 15 19:32:26 2010
@@ -28,11 +28,8 @@
 #include "svn_pools.h"
 
 #include "wc.h"
-#include "entries.h"
 #include "adm_files.h"
 #include "translate.h"
-#include "log.h"
-#include "lock.h"
 #include "workqueue.h"
 
 #include "private/svn_skel.h"
@@ -135,10 +132,16 @@ detranslate_wc_file(const char **detrans
   const char *eol;
   apr_hash_t *keywords;
   svn_boolean_t special;
+  svn_wc__db_kind_t kind;
+
+  SVN_ERR(svn_wc__db_read_kind(&kind, db, target_abspath, TRUE, scratch_pool));
 
   /* Decide if the merge target currently is a text or binary file. */
-  SVN_ERR(svn_wc__marked_as_binary(&is_binary, target_abspath, db,
-                                   scratch_pool));
+  if (kind == svn_wc__db_kind_file)
+    SVN_ERR(svn_wc__marked_as_binary(&is_binary, target_abspath, db,
+                                     scratch_pool));
+  else
+    is_binary = FALSE;
 
   /* See if we need to do a straight copy:
      - old and new mime-types are binary, or
@@ -160,18 +163,38 @@ detranslate_wc_file(const char **detrans
     {
       /* Old props indicate texty, new props indicate binary:
          detranslate keywords and old eol-style */
-      SVN_ERR(svn_wc__get_keywords(&keywords, db, target_abspath, NULL,
-                                   scratch_pool, scratch_pool));
-      SVN_ERR(svn_wc__get_special(&special, db, target_abspath, scratch_pool));
-      SVN_ERR(svn_wc__get_eol_style(&style, &eol, db, target_abspath,
-                                    scratch_pool, scratch_pool));
+      if (kind == svn_wc__db_kind_file)
+        SVN_ERR(svn_wc__get_translate_info(&style, &eol,
+                                           &keywords,
+                                           &special,
+                                           db, target_abspath,
+                                           scratch_pool, scratch_pool));
+      else
+        {
+          special = FALSE;
+          keywords = NULL;
+          eol = NULL;
+          style = svn_subst_eol_style_none;
+        }
     }
   else
     {
       /* New props indicate texty, regardless of old props */
 
       /* In case the file used to be special, detranslate specially */
-      SVN_ERR(svn_wc__get_special(&special, db, target_abspath, scratch_pool));
+      if (kind == svn_wc__db_kind_file)
+        SVN_ERR(svn_wc__get_translate_info(&style, &eol,
+                                           &keywords,
+                                           &special,
+                                           db, target_abspath,
+                                           scratch_pool, scratch_pool));
+      else
+        {
+          special = FALSE;
+          keywords = NULL;
+          eol = NULL;
+          style = svn_subst_eol_style_none;
+        }
 
       if (special)
         {
@@ -188,8 +211,9 @@ detranslate_wc_file(const char **detrans
               svn_subst_eol_style_from_value(&style, &eol, prop->value->data);
             }
           else if (!is_binary)
-            SVN_ERR(svn_wc__get_eol_style(&style, &eol, db, target_abspath,
-                                          scratch_pool, scratch_pool));
+            {
+              /* Already fetched */
+            }
           else
             {
               eol = NULL;
@@ -198,10 +222,7 @@ detranslate_wc_file(const char **detrans
 
           /* In case there were keywords, detranslate with keywords
              (iff we were texty) */
-          if (!is_binary)
-            SVN_ERR(svn_wc__get_keywords(&keywords, db, target_abspath, NULL,
-                                         scratch_pool, scratch_pool));
-          else
+          if (is_binary)
             keywords = NULL;
         }
     }
@@ -406,28 +427,29 @@ do_text_merge_external(svn_boolean_t *co
   return SVN_NO_ERROR;
 }
 
-/* Return a work item to copy/translate the merge result, obtained during
-   interactive conflict resolution, to the file RESULT_TARGET. The merge
-   result is expected in the same directory as TARGET_ABSPATH, with the same
-   basename as TARGET_ABSPATH, with a ".edited" extension.
+/* Create a new file in the same directory as VERSIONED_ABSPATH, with the
+   same basename as VERSIONED_ABSPATH, with a ".edited" extension, and set
+   *WORK_ITEM to a new work item that will copy and translate from the file
+   SOURCE to that new file.  It will be translated from repository-normal
+   form to working-copy form according to the versioned properties of
+   VERSIONED_ABSPATH that are current when the work item is executed.
 
-   DB should have a write lock for the directory containing RESULT_TARGET.
+   DB should have a write lock for the directory containing SOURCE.
 
-   *WORK_ITEM will be allocated in RESULT_POOL. All temporary allocations
-   will be allocated in SCRATCH_POOL.  */
+   Allocate *WORK_ITEM in RESULT_POOL. */
 static svn_error_t*
 save_merge_result(svn_skel_t **work_item,
                   svn_wc__db_t *db,
-                  const char *target_abspath,
-                  const char *result_target,
+                  const char *versioned_abspath,
+                  const char *source,
                   apr_pool_t *result_pool,
                   apr_pool_t *scratch_pool)
 {
   const char *edited_copy_abspath;
   const char *dir_abspath;
-  const char *merge_filename;
+  const char *filename;
 
-  svn_dirent_split(target_abspath, &dir_abspath, &merge_filename,
+  svn_dirent_split(&dir_abspath, &filename, versioned_abspath,
                    scratch_pool);
 
   /* ### Should use preserved-conflict-file-exts. */
@@ -435,42 +457,44 @@ save_merge_result(svn_skel_t **work_item
   SVN_ERR(svn_io_open_uniquely_named(NULL,
                                      &edited_copy_abspath,
                                      dir_abspath,
-                                     merge_filename,
+                                     filename,
                                      ".edited",
                                      svn_io_file_del_none,
                                      scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__loggy_translated_file(work_item,
-                                        db, dir_abspath,
-                                        edited_copy_abspath,
-                                        result_target,
-                                        target_abspath,
-                                        result_pool));
+  SVN_ERR(svn_wc__wq_build_file_copy_translated(work_item,
+                                                db, versioned_abspath,
+                                                source, edited_copy_abspath,
+                                                result_pool, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
-/* Deal with the RESULT of the conflict resolution callback.
- * LEFT, RIGHT, and MERGE_TARGET are the files involved in
- * the 3-way merge.  Store the result of the 3-way merge in
- * MERGE_OUTCOME.  If the callback did not provide the name to
- * a merged file, use RESULT_TARGET is a fallback.
- * DETRANSLATED_TARGET is the detranslated version of MERGE_TARGET
- * (see detranslate_wc_file() above).  OPTIONS are passed to the
- * diff3 implementation in case a 3-way  merge has to be carried out.
- * Do all allocations in POOL. */
+/* Deal with the result of the conflict resolution callback, as indicated by
+ * CHOICE.
+ *
+ * Set *WORK_ITEMS to new work items that will ...
+ * Set *MERGE_OUTCOME to the result of the 3-way merge.
+ *
+ * LEFT_ABSPATH, RIGHT_ABSPATH, and TARGET_ABSPATH are the input files to
+ * the 3-way merge, and MERGED_FILE is the merged result as generated by the
+ * internal or external merge or by the conflict resolution callback.
+ *
+ * DETRANSLATED_TARGET is the detranslated version of TARGET_ABSPATH
+ * (see detranslate_wc_file() above).  DIFF3_OPTIONS are passed to the
+ * diff3 implementation in case a 3-way merge has to be carried out. */
 static svn_error_t*
 eval_conflict_func_result(svn_skel_t **work_items,
                           enum svn_wc_merge_outcome_t *merge_outcome,
-                          svn_wc_conflict_result_t *result,
+                          svn_wc_conflict_choice_t choice,
                           svn_wc__db_t *db,
+                          const char *wri_abspath,
                           const char *left_abspath,
                           const char *right_abspath,
                           const char *target_abspath,
                           const char *copyfrom_text,
-                          const char *adm_abspath,
-                          const char *result_target,
+                          const char *merged_file,
                           const char *detranslated_target,
-                          svn_diff_file_options_t *options,
+                          svn_diff_file_options_t *diff3_options,
                           apr_pool_t *result_pool,
                           apr_pool_t *scratch_pool)
 {
@@ -480,7 +504,7 @@ eval_conflict_func_result(svn_skel_t **w
 
   *work_items = NULL;
 
-  switch (result->choice)
+  switch (choice)
     {
       /* If the callback wants to use one of the fulltexts
          to resolve the conflict, so be it.*/
@@ -511,11 +535,11 @@ eval_conflict_func_result(svn_skel_t **w
           svn_diff_t *diff;
           svn_diff_conflict_display_style_t style;
 
-          style = result->choice == svn_wc_conflict_choose_theirs_conflict
+          style = choice == svn_wc_conflict_choose_theirs_conflict
                     ? svn_diff_conflict_display_latest
                     : svn_diff_conflict_display_modified;
 
-          SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, adm_abspath,
+          SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, wri_abspath,
                                                  pool, pool));
           SVN_ERR(svn_stream_open_unique(&chosen_stream, &chosen_path,
                                          temp_dir,
@@ -524,7 +548,7 @@ eval_conflict_func_result(svn_skel_t **w
           SVN_ERR(svn_diff_file_diff3_2(&diff,
                                         left_abspath,
                                         detranslated_target, right_abspath,
-                                        options, pool));
+                                        diff3_options, pool));
           SVN_ERR(svn_diff_file_output_merge2(chosen_stream, diff,
                                               left_abspath,
                                               detranslated_target,
@@ -550,10 +574,7 @@ eval_conflict_func_result(svn_skel_t **w
            good to use". */
       case svn_wc_conflict_choose_merged:
         {
-          /* Look for callback's own merged-file first:  */
-          install_from = (result->merged_file
-                            ? result->merged_file
-                            : result_target);
+          install_from = merged_file;
           *merge_outcome = svn_wc_merge_merged;
           break;
         }
@@ -605,27 +626,30 @@ eval_conflict_func_result(svn_skel_t **w
   return SVN_NO_ERROR;
 }
 
-/* Preserve the three pre-merge files, and update the DB to track them.
+/* Preserve the three pre-merge files.
 
    Create three empty files, with unique names that each include the
    basename of TARGET_ABSPATH and one of LEFT_LABEL, RIGHT_LABEL and
    TARGET_LABEL, in the directory that contains TARGET_ABSPATH.  Typical
-   names are "foo.c.r37" or "foo.c.2.mine".
+   names are "foo.c.r37" or "foo.c.2.mine".  Set *LEFT_COPY, *RIGHT_COPY and
+   *TARGET_COPY to their absolute paths.
 
    Set *WORK_ITEMS to a list of new work items that will write copies of
    LEFT_ABSPATH, RIGHT_ABSPATH and TARGET_ABSPATH into the three files,
-   translated to working-copy form, and that will then update
-   TARGET_ABSPATH's entry in DB to track these files.
+   translated to working-copy form.
 
    The translation to working-copy form will be done according to the
-   versioned properties of TARGET_ABSPATH that are current at the point in
-   the work queue where these translating copies are performed.
+   versioned properties of TARGET_ABSPATH that are current when the work
+   queue items are executed.
 
-   ### TODO for WC-NG: Should update the DB outside the work queue: see
-       svn_wc__wq_tmp_build_set_text_conflict_markers()'s doc string.
+   If target_abspath is not versioned use detranslated_target_abspath
+   as the target file.
 */
 static svn_error_t *
 preserve_pre_merge_files(svn_skel_t **work_items,
+                         const char **left_copy,
+                         const char **right_copy,
+                         const char **target_copy,
                          svn_wc__db_t *db,
                          const char *left_abspath,
                          const char *right_abspath,
@@ -633,34 +657,35 @@ preserve_pre_merge_files(svn_skel_t **wo
                          const char *left_label,
                          const char *right_label,
                          const char *target_label,
+                         const char *detranslated_target_abspath,
                          svn_cancel_func_t cancel_func,
                          void *cancel_baton,
                          apr_pool_t *result_pool,
                          apr_pool_t *scratch_pool)
 {
-  const char *left_copy, *right_copy, *target_copy;
   const char *tmp_left, *tmp_right, *detranslated_target_copy;
   const char *dir_abspath, *target_name;
   const char *temp_dir;
   svn_skel_t *work_item;
+  svn_error_t *err;
 
   *work_items = NULL;
 
-  svn_dirent_split(target_abspath, &dir_abspath, &target_name, scratch_pool);
+  svn_dirent_split(&dir_abspath, &target_name, target_abspath, scratch_pool);
   SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, target_abspath,
                                          scratch_pool, scratch_pool));
 
   /* Create three empty files in DIR_ABSPATH, naming them with unique names
      that each include TARGET_NAME and one of {LEFT,RIGHT,TARGET}_LABEL,
-     and set {LEFT,RIGHT,TARGET}_COPY to those names. */
+     and set *{LEFT,RIGHT,TARGET}_COPY to those names. */
   SVN_ERR(svn_io_open_uniquely_named(
-            NULL, &left_copy, dir_abspath, target_name, left_label,
+            NULL, left_copy, dir_abspath, target_name, left_label,
             svn_io_file_del_none, scratch_pool, scratch_pool));
   SVN_ERR(svn_io_open_uniquely_named(
-            NULL, &right_copy, dir_abspath, target_name, right_label,
+            NULL, right_copy, dir_abspath, target_name, right_label,
             svn_io_file_del_none, scratch_pool, scratch_pool));
   SVN_ERR(svn_io_open_uniquely_named(
-            NULL, &target_copy, dir_abspath, target_name, target_label,
+            NULL, target_copy, dir_abspath, target_name, target_label,
             svn_io_file_del_none, scratch_pool, scratch_pool));
 
   /* We preserve all the files with keywords expanded and line
@@ -705,38 +730,42 @@ preserve_pre_merge_files(svn_skel_t **wo
   /* Create LEFT and RIGHT backup files, in expanded form.
      We use TARGET_ABSPATH's current properties to do the translation. */
   /* Derive the basenames of the 3 backup files. */
-  SVN_ERR(svn_wc__loggy_translated_file(&work_item, db, dir_abspath,
-                                        left_copy, tmp_left,
-                                        target_abspath, result_pool));
+  SVN_ERR(svn_wc__wq_build_file_copy_translated(&work_item,
+                                                db, target_abspath,
+                                                tmp_left, *left_copy,
+                                                result_pool, scratch_pool));
   *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
 
-  SVN_ERR(svn_wc__loggy_translated_file(&work_item, db, dir_abspath,
-                                        right_copy, tmp_right,
-                                        target_abspath, result_pool));
+  SVN_ERR(svn_wc__wq_build_file_copy_translated(&work_item,
+                                                 db, target_abspath,
+                                                 tmp_right, *right_copy,
+                                                 result_pool, scratch_pool));
   *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
 
   /* Back up TARGET_ABSPATH through detranslation/retranslation:
      the new translation properties may not match the current ones */
-  SVN_ERR(svn_wc__internal_translated_file(
+  err = svn_wc__internal_translated_file(
            &detranslated_target_copy, target_abspath, db, target_abspath,
            SVN_WC_TRANSLATE_TO_NF | SVN_WC_TRANSLATE_NO_OUTPUT_CLEANUP,
            cancel_func, cancel_baton,
-           scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__loggy_translated_file(&work_item, db, dir_abspath,
-                                        target_copy, detranslated_target_copy,
-                                        target_abspath, result_pool));
-  *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+           scratch_pool, scratch_pool);
 
-  /* Mark TARGET_ABSPATH's entry as "Conflicted", and start tracking
-     the backup files in the entry as well. */
-  SVN_ERR(svn_wc__wq_tmp_build_set_text_conflict_markers(
-                    &work_item,
-                    db, target_abspath,
-                    svn_dirent_basename(left_copy, NULL),
-                    svn_dirent_basename(right_copy, NULL),
-                    svn_dirent_basename(target_copy, NULL),
-                    result_pool, scratch_pool));
+  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+    {
+      svn_error_clear(err);
+
+      /* We are merging to a not versioned file, so we have handle
+         this without translation */
+      detranslated_target_copy = detranslated_target_abspath;
+    }
+  else
+    SVN_ERR(err);
 
+  SVN_ERR(svn_wc__wq_build_file_copy_translated(&work_item,
+                                                db, target_abspath,
+                                                detranslated_target_copy,
+                                                *target_copy,
+                                                result_pool, scratch_pool));
   *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
 
   return SVN_NO_ERROR;
@@ -773,6 +802,8 @@ setup_text_conflict_desc(const char *lef
 }
 
 /* XXX Insane amount of parameters... */
+/* RESULT_TARGET is the path to the merged file produced by the internal or
+   external 3-way merge. */
 static svn_error_t*
 maybe_resolve_conflicts(svn_skel_t **work_items,
                         svn_wc__db_t *db,
@@ -851,14 +882,15 @@ maybe_resolve_conflicts(svn_skel_t **wor
 
   SVN_ERR(eval_conflict_func_result(&work_item,
                                     merge_outcome,
-                                    result,
-                                    db,
+                                    result->choice,
+                                    db, dir_abspath,
                                     left_abspath,
                                     right_abspath,
                                     target_abspath,
                                     copyfrom_text,
-                                    dir_abspath,
-                                    result_target,
+                                    result->merged_file
+                                      ? result->merged_file
+                                      : result_target,
                                     detranslated_target,
                                     options,
                                     result_pool, scratch_pool));
@@ -870,18 +902,6 @@ maybe_resolve_conflicts(svn_skel_t **wor
     return SVN_NO_ERROR;
 
   /* The conflicts have not been dealt with. */
-  SVN_ERR(preserve_pre_merge_files(&work_item,
-                                   db,
-                                   left_abspath,
-                                   right_abspath,
-                                   target_abspath,
-                                   left_label,
-                                   right_label,
-                                   target_label,
-                                   cancel_func, cancel_baton,
-                                   result_pool, scratch_pool));
-  *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
-
   *merge_outcome = svn_wc_merge_conflict;
 
   return SVN_NO_ERROR;
@@ -923,7 +943,7 @@ merge_text_file(svn_skel_t **work_items,
 
   *work_items = NULL;
 
-  svn_dirent_split(target_abspath, &dir_abspath, &base_name, pool);
+  svn_dirent_split(&dir_abspath, &base_name, target_abspath, pool);
 
   /* Open a second temporary file for writing; this is where diff3
      will write the merged results.  We want to use a tempfile
@@ -940,7 +960,7 @@ merge_text_file(svn_skel_t **work_items,
   if (merge_options)
     SVN_ERR(svn_diff_file_options_parse(options, merge_options, pool));
 
-  /* Run an external merge if requested. */
+  /* Run the external or internal merge, as requested. */
   if (diff3_cmd)
       SVN_ERR(do_text_merge_external(&contains_conflicts,
                                      result_f,
@@ -965,7 +985,6 @@ merge_text_file(svn_skel_t **work_items,
                           options,
                           pool));
 
-  /* Close the output file */
   SVN_ERR(svn_io_file_close(result_f, pool));
 
   if (contains_conflicts && ! dry_run)
@@ -990,6 +1009,35 @@ merge_text_file(svn_skel_t **work_items,
                                       cancel_func, cancel_baton,
                                       result_pool, scratch_pool));
 
+      if (*merge_outcome == svn_wc_merge_conflict)
+        {
+          svn_skel_t *work_item;
+          const char *left_copy, *right_copy, *target_copy;
+
+          /* Preserve the three conflict files */
+          SVN_ERR(preserve_pre_merge_files(
+                    &work_item,
+                    &left_copy, &right_copy, &target_copy,
+                    db,
+                    left_abspath, right_abspath, target_abspath,
+                    left_label, right_label, target_label,
+                    detranslated_target_abspath,
+                    cancel_func, cancel_baton,
+                    result_pool, scratch_pool));
+          *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+
+          /* Track the three conflict files in the metadata.
+           * ### TODO WC-NG: Do this outside the work queue: see
+           * svn_wc__wq_tmp_build_set_text_conflict_markers()'s doc string. */
+          SVN_ERR(svn_wc__wq_tmp_build_set_text_conflict_markers(
+                            &work_item, db, target_abspath,
+                            svn_dirent_basename(left_copy, NULL),
+                            svn_dirent_basename(right_copy, NULL),
+                            svn_dirent_basename(target_copy, NULL),
+                            result_pool, scratch_pool));
+          *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);
+        }
+
       if (*merge_outcome == svn_wc_merge_merged)
         return SVN_NO_ERROR;
     }
@@ -1005,7 +1053,9 @@ merge_text_file(svn_skel_t **work_items,
          target file.  This is so we don't try to follow symlinks,
          but the same treatment is probably also appropriate for
          whatever special file types we may invent in the future. */
-      SVN_ERR(svn_wc__get_special(&special, db, target_abspath, pool));
+      SVN_ERR(svn_wc__get_translate_info(NULL, NULL, NULL,
+                                         &special, db, target_abspath,
+                                         pool, pool));
       SVN_ERR(svn_io_files_contents_same_p(&same, result_target,
                                            (special ?
                                               detranslated_target_abspath :
@@ -1066,7 +1116,7 @@ merge_binary_file(svn_skel_t **work_item
 
   *work_items = NULL;
 
-  svn_dirent_split(target_abspath, &merge_dirpath, &merge_filename, pool);
+  svn_dirent_split(&merge_dirpath, &merge_filename, target_abspath, pool);
 
   /* Give the conflict resolution callback a chance to clean
      up the conflict before we mark the file 'conflicted' */
@@ -1187,11 +1237,10 @@ merge_binary_file(svn_skel_t **work_item
                                          target_label,
                                          svn_io_file_del_none,
                                          pool, pool));
-      SVN_ERR(svn_wc__loggy_move(work_items, db,
-                                 merge_dirpath,
-                                 detranslated_target_abspath,
-                                 mine_copy,
-                                 result_pool));
+      SVN_ERR(svn_wc__wq_build_file_move(work_items, db,
+                                         detranslated_target_abspath,
+                                         mine_copy,
+                                         pool, result_pool));
 
       mine_copy = svn_dirent_is_child(merge_dirpath,
                                       mine_copy, pool);

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/node.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/node.c Wed Sep 15 19:32:26 2010
@@ -45,9 +45,7 @@
 #include "svn_types.h"
 
 #include "wc.h"
-#include "lock.h"
 #include "props.h"
-#include "log.h"
 #include "entries.h"
 #include "wc_db.h"
 
@@ -136,9 +134,7 @@ svn_wc__node_get_repos_info(const char *
       return SVN_NO_ERROR;
     }
 
-  if (scan_added
-      && (status == svn_wc__db_status_added
-          || status == svn_wc__db_status_obstructed_add))
+  if (scan_added && (status == svn_wc__db_status_added))
     {
       /* We have an addition. scan_addition() will find the intended
          repository location by scanning up the tree.  */
@@ -147,7 +143,7 @@ svn_wc__node_get_repos_info(const char *
                                 NULL, repos_root_url, repos_uuid,
                                 NULL, NULL, NULL, NULL,
                                 wc_ctx->db, local_abspath,
-                                scratch_pool, scratch_pool));
+                                result_pool, scratch_pool));
     }
 
   /* If we didn't get repository information, and the status means we are
@@ -155,12 +151,10 @@ svn_wc__node_get_repos_info(const char *
   if (((repos_root_url != NULL && *repos_root_url == NULL)
        || (repos_uuid != NULL && *repos_uuid == NULL))
       && (status == svn_wc__db_status_normal
-          || status == svn_wc__db_status_obstructed
           || status == svn_wc__db_status_absent
           || status == svn_wc__db_status_excluded
           || status == svn_wc__db_status_not_present
-          || (scan_deleted && (status == svn_wc__db_status_deleted))
-          || (scan_deleted && (status == svn_wc__db_status_obstructed_delete))))
+          || (scan_deleted && (status == svn_wc__db_status_deleted))))
     {
       SVN_ERR(svn_wc__db_scan_base_repos(NULL, repos_root_url, repos_uuid,
                                          wc_ctx->db, local_abspath,
@@ -174,15 +168,20 @@ svn_wc__node_get_repos_info(const char *
 svn_error_t *
 svn_wc_read_kind(svn_node_kind_t *kind,
                  svn_wc_context_t *wc_ctx,
-                 const char *abspath,
+                 const char *local_abspath,
                  svn_boolean_t show_hidden,
                  apr_pool_t *scratch_pool)
 {
+  svn_wc__db_status_t db_status;
   svn_wc__db_kind_t db_kind;
   svn_error_t *err;
 
-  err = svn_wc__db_read_kind(&db_kind, wc_ctx->db, abspath, FALSE,
-                             scratch_pool);
+  err = svn_wc__db_read_info(&db_status, &db_kind, NULL, NULL, NULL, NULL,
+                             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                             NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                             NULL, NULL, NULL,
+                             wc_ctx->db, local_abspath,
+                             scratch_pool, scratch_pool);
 
   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
     {
@@ -213,14 +212,16 @@ svn_wc_read_kind(svn_node_kind_t *kind,
 
   /* Make sure hidden nodes return svn_node_none. */
   if (! show_hidden)
-    {
-      svn_boolean_t hidden;
-
-      SVN_ERR(svn_wc__db_node_hidden(&hidden, wc_ctx->db, abspath,
-                                     scratch_pool));
-      if (hidden)
-        *kind = svn_node_none;
-    }
+    switch (db_status)
+      {
+        case svn_wc__db_status_not_present:
+        case svn_wc__db_status_absent:
+        case svn_wc__db_status_excluded:
+          *kind = svn_node_none;
+
+        default:
+          break;
+      }
 
   return SVN_NO_ERROR;
 }
@@ -340,18 +341,7 @@ svn_wc__internal_node_get_url(const char
                                scratch_pool, scratch_pool));
   if (repos_relpath == NULL)
     {
-      if (status == svn_wc__db_status_normal
-          || status == svn_wc__db_status_incomplete
-          || (have_base
-              && (status == svn_wc__db_status_deleted
-                  || status == svn_wc__db_status_obstructed_delete)))
-        {
-          SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
-                                             NULL,
-                                             db, local_abspath,
-                                             scratch_pool, scratch_pool));
-        }
-      else if (status == svn_wc__db_status_added)
+      if (status == svn_wc__db_status_added)
         {
           SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, &repos_relpath,
                                            &repos_root_url, NULL, NULL, NULL,
@@ -359,16 +349,25 @@ svn_wc__internal_node_get_url(const char
                                            db, local_abspath,
                                            scratch_pool, scratch_pool));
         }
+      else if (have_base)
+        {
+          SVN_ERR(svn_wc__db_scan_base_repos(&repos_relpath, &repos_root_url,
+                                             NULL,
+                                             db, local_abspath,
+                                             scratch_pool, scratch_pool));
+        }
       else if (status == svn_wc__db_status_absent
                || status == svn_wc__db_status_excluded
                || status == svn_wc__db_status_not_present
-               || (!have_base
-                   && (status == svn_wc__db_status_deleted
-                       || status == svn_wc__db_status_obstructed_delete)))
+               || (!have_base && (status == svn_wc__db_status_deleted)))
         {
           const char *parent_abspath;
 
-          svn_dirent_split(local_abspath, &parent_abspath, &repos_relpath,
+          /* Set 'repos_root_url' to the *full URL* of the parent WC dir,
+           * and 'repos_relpath' to the *single path component* that is the
+           * basename of this WC directory, so that joining them will result
+           * in the correct full URL. */
+          svn_dirent_split(&parent_abspath, &repos_relpath, local_abspath,
                            scratch_pool);
           SVN_ERR(svn_wc__internal_node_get_url(&repos_root_url, db,
                                                 parent_abspath,
@@ -402,21 +401,89 @@ svn_wc__node_get_url(const char **url,
                             result_pool, scratch_pool));
 }
 
+/* ### This is essentially a copy-paste of svn_wc__internal_get_url(). 
+ * ### If we decide to keep this one, then it should be rewritten to avoid
+ * ### code duplication.*/
 svn_error_t *
-svn_wc__node_get_copyfrom_info(const char **copyfrom_url,
-                               svn_revnum_t *copyfrom_rev,
-                               svn_boolean_t *is_copy_target,
+svn_wc__node_get_repos_relpath(const char **repos_relpath,
                                svn_wc_context_t *wc_ctx,
                                const char *local_abspath,
                                apr_pool_t *result_pool,
                                apr_pool_t *scratch_pool)
 {
-  svn_wc__db_t *db = wc_ctx->db;
+  svn_wc__db_status_t status;
+  svn_boolean_t have_base;
+
+  SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, repos_relpath,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, &have_base, NULL, NULL, NULL,
+                               wc_ctx->db, local_abspath,
+                               result_pool, scratch_pool));
+  if (*repos_relpath == NULL)
+    {
+      if (status == svn_wc__db_status_added)
+        {
+          SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, repos_relpath,
+                                           NULL, NULL, NULL, NULL,
+                                           NULL, NULL,
+                                           wc_ctx->db, local_abspath,
+                                           result_pool, scratch_pool));
+        }
+      else if (have_base)
+        {
+          SVN_ERR(svn_wc__db_scan_base_repos(repos_relpath, NULL,
+                                             NULL,
+                                             wc_ctx->db, local_abspath,
+                                             result_pool, scratch_pool));
+        }
+      else if (status == svn_wc__db_status_excluded
+               || (!have_base && (status == svn_wc__db_status_deleted)))
+        {
+          const char *parent_abspath, *name, *parent_relpath;
+
+          svn_dirent_split(&parent_abspath, &name, local_abspath,
+                           scratch_pool);
+          SVN_ERR(svn_wc__node_get_repos_relpath(&parent_relpath, wc_ctx,
+                                                 parent_abspath,
+                                                 scratch_pool,
+                                                 scratch_pool));
+
+          if (parent_relpath)
+            *repos_relpath = svn_relpath_join(parent_relpath, name,
+                                              result_pool);
+        }
+      else
+        {
+          /* Status: obstructed, obstructed_add */
+          *repos_relpath = NULL;
+          return SVN_NO_ERROR;
+        }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__internal_get_copyfrom_info(const char **copyfrom_root_url,
+                                   const char **copyfrom_repos_relpath,
+                                   const char **copyfrom_url,
+                                   svn_revnum_t *copyfrom_rev,
+                                   svn_boolean_t *is_copy_target,
+                                   svn_wc__db_t *db,
+                                   const char *local_abspath,
+                                   apr_pool_t *result_pool,
+                                   apr_pool_t *scratch_pool)
+{
   const char *original_root_url;
   const char *original_repos_relpath;
   svn_revnum_t original_revision;
   svn_wc__db_status_t status;
 
+  if (copyfrom_root_url)
+    *copyfrom_root_url = NULL;
+  if (copyfrom_repos_relpath)
+    *copyfrom_repos_relpath = NULL;
   if (copyfrom_url)
     *copyfrom_url = NULL;
   if (copyfrom_rev)
@@ -429,7 +496,7 @@ svn_wc__node_get_copyfrom_info(const cha
                                NULL, &original_repos_relpath,
                                &original_root_url, NULL, &original_revision,
                                NULL, NULL, NULL, NULL, NULL, db,
-                               local_abspath, scratch_pool, scratch_pool));
+                               local_abspath, result_pool, scratch_pool));
   if (original_root_url && original_repos_relpath)
     {
       /* If this was the root of the copy then the URL is immediately
@@ -441,6 +508,10 @@ svn_wc__node_get_copyfrom_info(const cha
                                                       original_repos_relpath,
                                                       result_pool);
 
+      if (copyfrom_root_url)
+        *copyfrom_root_url = original_root_url;
+      if (copyfrom_repos_relpath)
+        *copyfrom_repos_relpath = original_repos_relpath;
       if (copyfrom_url)
         *copyfrom_url = my_copyfrom_url;
 
@@ -465,15 +536,17 @@ svn_wc__node_get_copyfrom_info(const cha
           const char *base_name;
           const char *parent_copyfrom_url;
 
-          svn_dirent_split(local_abspath, &parent_abspath, &base_name,
+          svn_dirent_split(&parent_abspath, &base_name, local_abspath,
                            scratch_pool);
 
           /* This is a copied node, so we should never fall off the top of a
            * working copy here. */
-          SVN_ERR(svn_wc__node_get_copyfrom_info(&parent_copyfrom_url,
-                                                 NULL, NULL,
-                                                 wc_ctx, parent_abspath,
-                                                 scratch_pool, scratch_pool));
+          SVN_ERR(svn_wc__internal_get_copyfrom_info(NULL, NULL,
+                                                     &parent_copyfrom_url,
+                                                     NULL, NULL,
+                                                     db, parent_abspath,
+                                                     scratch_pool,
+                                                     scratch_pool));
 
           /* So, count this as a separate copy target only if the URLs
            * don't match up, or if the parent isn't copied at all. */
@@ -485,9 +558,9 @@ svn_wc__node_get_copyfrom_info(const cha
             *is_copy_target = TRUE;
         }
     }
-  else if ((status == svn_wc__db_status_added
-            || status == svn_wc__db_status_obstructed_add)
-           && (copyfrom_rev || copyfrom_url))
+  else if ((status == svn_wc__db_status_added)
+           && (copyfrom_rev || copyfrom_url || copyfrom_root_url
+               || copyfrom_repos_relpath))
     {
       /* ...But if this is merely the descendant of an explicitly
          copied/moved directory, we need to do a bit more work to
@@ -498,7 +571,7 @@ svn_wc__node_get_copyfrom_info(const cha
                                        NULL, &original_repos_relpath,
                                        &original_root_url, NULL,
                                        &original_revision, db, local_abspath,
-                                       scratch_pool, scratch_pool));
+                                       result_pool, scratch_pool));
       if (status == svn_wc__db_status_copied ||
           status == svn_wc__db_status_moved_here)
         {
@@ -512,6 +585,12 @@ svn_wc__node_get_copyfrom_info(const cha
                                             scratch_pool);
           if (src_relpath)
             {
+              if (copyfrom_root_url)
+                *copyfrom_root_url = original_root_url;
+              if (copyfrom_repos_relpath)
+                *copyfrom_repos_relpath = svn_relpath_join(
+                                            original_repos_relpath,
+                                            src_relpath, result_pool);
               if (copyfrom_url)
                 *copyfrom_url = svn_path_url_add_component2(src_parent_url,
                                                             src_relpath,
@@ -525,8 +604,39 @@ svn_wc__node_get_copyfrom_info(const cha
   return SVN_NO_ERROR;
 }
 
-
-/* A recursive node-walker, helper for svn_wc__node_walk_children(). */
+svn_error_t *
+svn_wc__node_get_copyfrom_info(const char **copyfrom_root_url,
+                               const char **copyfrom_repos_relpath,
+                               const char **copyfrom_url,
+                               svn_revnum_t *copyfrom_rev,
+                               svn_boolean_t *is_copy_target,
+                               svn_wc_context_t *wc_ctx,
+                               const char *local_abspath,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool)
+{
+  return
+    svn_error_return(svn_wc__internal_get_copyfrom_info(copyfrom_root_url,
+                                                        copyfrom_repos_relpath,
+                                                        copyfrom_url,
+                                                        copyfrom_rev,
+                                                        is_copy_target,
+                                                        wc_ctx->db,
+                                                        local_abspath,
+                                                        result_pool,
+                                                        scratch_pool));
+}
+
+/* A recursive node-walker, helper for svn_wc__node_walk_children().
+ *
+ * Call WALK_CALLBACK with WALK_BATON on all children (recursively) of
+ * DIR_ABSPATH in DB, but not on DIR_ABSPATH itself. DIR_ABSPATH must be a
+ * versioned directory. If SHOW_HIDDEN is true, visit hidden nodes, else
+ * ignore them. Restrict the depth of the walk to DEPTH.
+ *
+ * ### Is it possible for a subdirectory to be hidden and known to be a
+ *     directory?  If so, and if show_hidden is true, this will try to
+ *     recurse into it.  */
 static svn_error_t *
 walker_helper(svn_wc__db_t *db,
               const char *dir_abspath,
@@ -553,6 +663,7 @@ walker_helper(svn_wc__db_t *db,
     {
       const char *child_abspath;
       svn_wc__db_kind_t child_kind;
+      svn_wc__db_status_t child_status;
 
       svn_pool_clear(iterpool);
 
@@ -565,27 +676,31 @@ walker_helper(svn_wc__db_t *db,
                                                     const char *),
                                       iterpool);
 
-      if (!show_hidden)
-        {
-          svn_boolean_t hidden;
-
-          SVN_ERR(svn_wc__db_node_hidden(&hidden, db, child_abspath, iterpool));
-          if (hidden)
-            continue;
-        }
-
-      SVN_ERR(svn_wc__db_read_info(NULL, &child_kind, NULL, NULL, NULL, NULL,
+      SVN_ERR(svn_wc__db_read_info(&child_status, &child_kind, NULL, NULL,
                                    NULL, NULL, NULL, NULL, NULL, NULL,
                                    NULL, NULL, NULL, NULL, NULL, NULL,
                                    NULL, NULL, NULL, NULL, NULL,
-                                   NULL,
+                                   NULL, NULL, NULL,
                                    db, child_abspath, iterpool, iterpool));
 
+      if (!show_hidden)
+        switch (child_status)
+          {
+            case svn_wc__db_status_not_present:
+            case svn_wc__db_status_absent:
+            case svn_wc__db_status_excluded:
+              continue;
+            default:
+              break;
+          }
+
       /* Return the child, if appropriate.  (For a directory,
        * this is the first visit: as a child.) */
       if (child_kind == svn_wc__db_kind_file
             || depth >= svn_depth_immediates)
         {
+          /* ### Maybe we should pass kind to the callback?.
+             ### almost every callee starts by asking for this */
           SVN_ERR(walk_callback(child_abspath, walk_baton, iterpool));
         }
 
@@ -623,26 +738,28 @@ svn_wc__internal_walk_children(svn_wc__d
                                apr_pool_t *scratch_pool)
 {
   svn_wc__db_kind_t kind;
-  svn_depth_t depth;
+  svn_wc__db_status_t status;
+
+  SVN_ERR_ASSERT(walk_depth >= svn_depth_empty
+                 && walk_depth <= svn_depth_infinity);
 
-  SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, &depth, NULL,
+  /* Check if the node exists before the first callback */
+  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,
                                db, local_abspath, scratch_pool, scratch_pool));
 
-  if (kind == svn_wc__db_kind_file || depth == svn_depth_exclude)
-    {
-      return svn_error_return(
-        walk_callback(local_abspath, walk_baton, scratch_pool));
-    }
+  SVN_ERR(walk_callback(local_abspath, walk_baton, scratch_pool));
+
+  if (kind == svn_wc__db_kind_file
+      || status == svn_wc__db_status_not_present
+      || status == svn_wc__db_status_excluded
+      || status == svn_wc__db_status_absent)
+    return SVN_NO_ERROR;
 
   if (kind == svn_wc__db_kind_dir)
     {
-      /* Return the directory first, before starting recursion, since it
-         won't get returned as part of the recursion. */
-      SVN_ERR(walk_callback(local_abspath, walk_baton, scratch_pool));
-
       return svn_error_return(
         walker_helper(db, local_abspath, show_hidden, walk_callback, walk_baton,
                       walk_depth, cancel_func, cancel_baton, scratch_pool));
@@ -687,31 +804,7 @@ svn_wc__node_is_status_deleted(svn_boole
                                wc_ctx->db, local_abspath,
                                scratch_pool, scratch_pool));
 
-  *is_deleted = (status == svn_wc__db_status_deleted) ||
-                (status == svn_wc__db_status_obstructed_delete);
-
-  return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_wc__node_is_status_obstructed(svn_boolean_t *is_obstructed,
-                                  svn_wc_context_t *wc_ctx,
-                                  const char *local_abspath,
-                                  apr_pool_t *scratch_pool)
-{
-  svn_wc__db_status_t status;
-
-  SVN_ERR(svn_wc__db_read_info(&status,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL,
-                               wc_ctx->db, local_abspath,
-                               scratch_pool, scratch_pool));
-
-  *is_obstructed = (status == svn_wc__db_status_obstructed) ||
-                   (status == svn_wc__db_status_obstructed_add) ||
-                   (status == svn_wc__db_status_obstructed_delete);
+  *is_deleted = (status == svn_wc__db_status_deleted);
 
   return SVN_NO_ERROR;
 }
@@ -771,8 +864,7 @@ svn_wc__node_is_added(svn_boolean_t *is_
                                NULL, NULL,
                                wc_ctx->db, local_abspath,
                                scratch_pool, scratch_pool));
-  *is_added = (status == svn_wc__db_status_added
-               || status == svn_wc__db_status_obstructed_add);
+  *is_added = (status == svn_wc__db_status_added);
 
   return SVN_NO_ERROR;
 }
@@ -807,8 +899,7 @@ svn_wc__internal_is_replaced(svn_boolean
                                      db, local_abspath,
                                      scratch_pool, scratch_pool));
 
-  *replaced = ((status == svn_wc__db_status_added
-                || status == svn_wc__db_status_obstructed_add)
+  *replaced = ((status == svn_wc__db_status_added)
                && have_base
                && base_status != svn_wc__db_status_not_present);
 
@@ -889,13 +980,13 @@ svn_wc__node_get_working_rev_info(svn_re
 
   if (status == svn_wc__db_status_deleted)
     {
-      const char *work_del_abspath = NULL;
-      const char *base_del_abspath = NULL;
+      const char *work_del_abspath;
+      const char *base_del_abspath;
 
       SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, NULL,
                                        NULL, &work_del_abspath, wc_ctx->db,
                                        local_abspath, scratch_pool,
-                                       result_pool));
+                                       scratch_pool));
       if (work_del_abspath)
         {
           SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, NULL, NULL,
@@ -1002,8 +1093,7 @@ svn_wc__node_get_commit_base_rev(svn_rev
                                        wc_ctx->db, parent_abspath,
                                        scratch_pool, scratch_pool));
 
-          SVN_ERR_ASSERT(parent_status == svn_wc__db_status_added
-                         || parent_status == svn_wc__db_status_obstructed_add);
+          SVN_ERR_ASSERT(parent_status == svn_wc__db_status_added);
 
           SVN_ERR(svn_wc__db_scan_addition(NULL, NULL, NULL, NULL, NULL, NULL,
                                            NULL, NULL,
@@ -1119,31 +1209,258 @@ svn_wc__node_check_conflicts(svn_boolean
 }
 
 svn_error_t *
-svn_wc__temp_get_keep_local(svn_boolean_t *keep_local,
-                            svn_wc_context_t *wc_ctx,
-                            const char *local_abspath,
-                            apr_pool_t *scratch_pool)
+svn_wc__internal_node_get_schedule(svn_wc_schedule_t *schedule,
+                                   svn_boolean_t *copied,
+                                   svn_wc__db_t *db,
+                                   const char *local_abspath,
+                                   apr_pool_t *scratch_pool)
 {
-  svn_boolean_t is_deleted;
+  svn_wc__db_status_t status;
+  svn_boolean_t has_base;
+  const char *copyfrom_relpath;
 
-  SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, wc_ctx, local_abspath,
-                                         scratch_pool));
-  if (is_deleted)
-    SVN_ERR(svn_wc__db_temp_determine_keep_local(keep_local, wc_ctx->db,
-                                                 local_abspath, scratch_pool));
-  else
-    *keep_local = FALSE;
+  if (schedule)
+    *schedule = svn_wc_schedule_normal;
+  if (copied)
+    *copied = FALSE;
+
+  SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               &copyfrom_relpath, NULL, NULL, NULL, NULL,
+                               &has_base, NULL, NULL, NULL,
+                               db, local_abspath, scratch_pool, scratch_pool));
+
+  switch (status)
+    {
+      case svn_wc__db_status_not_present:
+      case svn_wc__db_status_absent:
+      case svn_wc__db_status_excluded:
+        return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
+                                 _("'%s' is not under version control"),
+                                 svn_dirent_local_style(local_abspath,
+                                                        scratch_pool));
+
+      case svn_wc__db_status_normal:
+      case svn_wc__db_status_incomplete:
+        break;
+
+      case svn_wc__db_status_deleted:
+        {
+          const char *work_del_abspath;
+
+          if (schedule)
+            *schedule = svn_wc_schedule_delete;
+
+          if (!copied)
+            break;
+
+          /* Find out details of our deletion.  */
+          SVN_ERR(svn_wc__db_scan_deletion(NULL,
+                                           NULL,
+                                           NULL,
+                                           &work_del_abspath,
+                                           db, local_abspath,
+                                           scratch_pool, scratch_pool));
+
+          if (!work_del_abspath)
+            break; /* Base deletion */
+
+          /* We miss the 4th tree to properly find out if this is
+             the root of a working-delete. Only in that case
+             should copied be set to true. See entries.c for details. */
+
+          *copied = FALSE; /* Until we can fix this test */
+          break;
+        }
+      case svn_wc__db_status_added:
+        {
+          const char *op_root_abspath;
+          const char *parent_abspath;
+          const char *parent_copyfrom_relpath;
+          const char *child_name;
+
+          if (schedule)
+            *schedule = svn_wc_schedule_add;
+
+          if (copyfrom_relpath != NULL)
+            {
+              status = svn_wc__db_status_copied; /* Or moved */
+              op_root_abspath = local_abspath;
+            }
+          else
+            SVN_ERR(svn_wc__db_scan_addition(&status,
+                                             &op_root_abspath,
+                                             NULL, NULL, NULL,
+                                             &copyfrom_relpath,
+                                             NULL, NULL, NULL,
+                                             db, local_abspath,
+                                             scratch_pool, scratch_pool));
+
+          if (copied && status != svn_wc__db_status_added)
+            *copied = TRUE;
+
+          if (!schedule)
+            break;
+
+          if (has_base)
+            {
+              svn_wc__db_status_t base_status;
+              SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL, NULL,
+                                               NULL, NULL, NULL, NULL, NULL,
+                                               NULL, NULL, NULL, NULL, NULL,
+                                               NULL,
+                                               db, local_abspath,
+                                               scratch_pool, scratch_pool));
+
+              if (base_status != svn_wc__db_status_not_present)
+                *schedule = svn_wc_schedule_replace;
+            }
+
+          if (status == svn_wc__db_status_added)
+            break; /* Local addition */
+
+          /* Determine the parent status to check if we should show the
+             schedule of a child of a copy as normal. */
+          if (strcmp(op_root_abspath, local_abspath) != 0)
+            {
+              *schedule = svn_wc_schedule_normal;
+              break; /* Part of parent copy */
+            }
+
+          /* When we used entries we didn't see just a different revision
+             as a new operational root, so we have to check if the parent
+             is from the same copy origin */
+          parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
+
+          SVN_ERR(svn_wc__db_read_info(&status, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL,
+                                       &parent_copyfrom_relpath, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       db, parent_abspath,
+                                       scratch_pool, scratch_pool));
+
+          if (status != svn_wc__db_status_added)
+            break; /* Parent was not added */
+
+          if (!parent_copyfrom_relpath)
+            {
+              SVN_ERR(svn_wc__db_scan_addition(&status, &op_root_abspath, NULL,
+                                               NULL, NULL,
+                                               &parent_copyfrom_relpath, NULL,
+                                               NULL, NULL,
+                                               db, parent_abspath,
+                                               scratch_pool, scratch_pool));
+
+              if (!parent_copyfrom_relpath)
+                break; /* Parent is a local addition */
+
+              parent_copyfrom_relpath = svn_relpath_join(
+                                           parent_copyfrom_relpath,
+                                           svn_dirent_is_child(op_root_abspath,
+                                                               parent_abspath,
+                                                               NULL),
+                                           scratch_pool);
+            }
+
+
+          child_name = svn_relpath_is_child(parent_copyfrom_relpath,
+                                            copyfrom_relpath, NULL);
+
+          if (!child_name
+              || strcmp(child_name, svn_dirent_basename(local_abspath, NULL)))
+            break; /* Different operation */
+
+          *schedule = svn_wc_schedule_normal;
+          break;
+        }
+      default:
+        SVN_ERR_MALFUNCTION();
+    }
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-svn_wc__temp_get_wclocked(svn_boolean_t *locked,
+svn_wc__node_get_schedule(svn_wc_schedule_t *schedule,
+                          svn_boolean_t *copied,
                           svn_wc_context_t *wc_ctx,
                           const char *local_abspath,
                           apr_pool_t *scratch_pool)
 {
   return svn_error_return(
-              svn_wc__db_wclocked(locked, wc_ctx->db, local_abspath,
-                                  scratch_pool));
+           svn_wc__internal_node_get_schedule(schedule,
+                                              copied,
+                                              wc_ctx->db,
+                                              local_abspath,
+                                              scratch_pool));
+}
+
+svn_error_t *
+svn_wc__node_get_info_bits(apr_time_t *text_time,
+                           const char **conflict_old,
+                           const char **conflict_new,
+                           const char **conflict_wrk,
+                           const char **prejfile,
+                           svn_wc_context_t *wc_ctx,
+                           const char *local_abspath,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
+{
+  svn_boolean_t conflicted;
+
+  SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, text_time, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               &conflicted, NULL,
+                               wc_ctx->db, local_abspath,
+                               scratch_pool, scratch_pool));
+
+  if (conflict_old)
+    *conflict_old = NULL;
+  if (conflict_new)
+    *conflict_new = NULL;
+  if (conflict_wrk)
+    *conflict_wrk = NULL;
+  if (prejfile)
+    *prejfile = NULL;
+
+  if (conflicted
+      && (conflict_old || conflict_new || conflict_wrk || prejfile))
+    {
+      const apr_array_header_t *conflicts;
+      int j;
+      SVN_ERR(svn_wc__db_read_conflicts(&conflicts, wc_ctx->db, local_abspath,
+                                        scratch_pool, scratch_pool));
+
+      for (j = 0; j < conflicts->nelts; j++)
+        {
+          const svn_wc_conflict_description2_t *cd;
+          cd = APR_ARRAY_IDX(conflicts, j,
+                             const svn_wc_conflict_description2_t *);
+
+          switch (cd->kind)
+            {
+            case svn_wc_conflict_kind_text:
+              if (conflict_old)
+                *conflict_old = apr_pstrdup(result_pool, cd->base_file);
+
+              if (conflict_new)
+                *conflict_new = apr_pstrdup(result_pool, cd->their_file);
+
+              if (conflict_wrk)
+                *conflict_wrk = apr_pstrdup(result_pool, cd->my_file);
+              break;
+
+            case svn_wc_conflict_kind_property:
+              if (prejfile)
+                *prejfile = apr_pstrdup(result_pool, cd->their_file);
+              break;
+            case svn_wc_conflict_kind_tree:
+              break;
+            }
+        }
+    }
+
+  return SVN_NO_ERROR;
 }

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_wc/old-and-busted.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_wc/old-and-busted.c?rev=997472&r1=997471&r2=997472&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_wc/old-and-busted.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_wc/old-and-busted.c Wed Sep 15 19:32:26 2010
@@ -164,7 +164,7 @@ read_str(const char **result,
             svn_stringbuf_appendbytes(s, start, *buf - start);
           (*buf)++;
           SVN_ERR(read_escaped(&c, buf, end));
-          svn_stringbuf_appendbytes(s, &c, 1);
+          svn_stringbuf_appendbyte(s, c);
           start = *buf;
         }
       else
@@ -1307,7 +1307,7 @@ svn_wc_entry(const svn_wc_entry_t **entr
 
       const char *dir_abspath;
 
-      svn_dirent_split(local_abspath, &dir_abspath, &entry_name, pool);
+      svn_dirent_split(&dir_abspath, &entry_name, local_abspath, pool);
 
       dir_access = svn_wc__adm_retrieve_internal2(db, dir_abspath, pool);
     }