You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/07/23 21:37:24 UTC

svn commit: r967221 [4/7] - in /subversion/branches/atomic-revprop: ./ build/generator/ notes/ notes/tree-conflicts/ subversion/bindings/javahl/tests/org/apache/subversion/javahl/ subversion/bindings/javahl/tests/org/tigris/subversion/javahl/ subversio...

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/log.h
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/log.h?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/log.h (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/log.h Fri Jul 23 19:37:19 2010
@@ -47,22 +47,6 @@ extern "C" {
    ADM_ABSPATH (or equal to it, where that makes sense).
 */
 
-
-/* Set *WORK_ITEM to a work queue instruction to generate a translated
-   file from SRC_ABSPATH to DST_ABSPATH with translation settings from
-   VERSIONED_ABSPATH.
-
-   ADM_ABSPATH is described above.
-*/
-svn_error_t *
-svn_wc__loggy_translated_file(svn_skel_t **work_item,
-                              svn_wc__db_t *db,
-                              const char *adm_abspath,
-                              const char *dst_abspath,
-                              const char *src_abspath,
-                              const char *versioned_abspath,
-                              apr_pool_t *result_pool);
-
 /* Set *WORK_ITEM to a work queue instruction to delete the entry
    associated with LOCAL_ABSPATH from the entries file.
 
@@ -81,40 +65,6 @@ svn_wc__loggy_delete_entry(svn_skel_t **
                            svn_wc__db_kind_t kind,
                            apr_pool_t *result_pool);
 
-/* Set *WORK_ITEM to a work queue instruction to move the file SRC_ABSPATH
-   to DST_ABSPATH.
-
-   The file SRC_ABSPATH must exist.  The test for existence is made now, not
-   at log run time.
-
-   Set *DST_MODIFIED (if DST_MODIFIED isn't NULL) to indicate whether the
-   destination path will have been modified after running the log: if either
-   the move or the remove will have been carried out.
-
-   ADM_ABSPATH is described above.
-*/
-svn_error_t *
-svn_wc__loggy_move(svn_skel_t **work_item,
-                   svn_wc__db_t *db,
-                   const char *adm_abspath,
-                   const char *src_abspath,
-                   const char *dst_abspath,
-                   apr_pool_t *result_pool);
-
-
-/* Set *WORK_ITEM to a work queue instruction to set the timestamp of
-   LOCAL_ABSPATH to the time TIMESTR.
-
-   ADM_ABSPATH is described above.
-*/
-svn_error_t *
-svn_wc__loggy_set_timestamp(svn_skel_t **work_item,
-                            svn_wc__db_t *db,
-                            const char *adm_abspath,
-                            const char *local_abspath,
-                            const char *timestr,
-                            apr_pool_t *result_pool);
-
 /* Set *WORK_ITEM to a work queue instruction to
    ### ...
 

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/merge.c?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/merge.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/merge.c Fri Jul 23 19:37:19 2010
@@ -134,10 +134,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
@@ -159,18 +165,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)
         {
@@ -187,8 +213,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;
@@ -197,10 +224,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;
         }
     }
@@ -439,12 +463,10 @@ save_merge_result(svn_skel_t **work_item
                                      ".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,
-                                        source,
-                                        versioned_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;
 }
@@ -621,6 +643,9 @@ eval_conflict_func_result(svn_skel_t **w
    The translation to working-copy form will be done according to the
    versioned properties of TARGET_ABSPATH that are current when the work
    queue items are executed.
+
+   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,
@@ -634,6 +659,7 @@ 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,
@@ -643,6 +669,7 @@ preserve_pre_merge_files(svn_skel_t **wo
   const char *dir_abspath, *target_name;
   const char *temp_dir;
   svn_skel_t *work_item;
+  svn_error_t *err;
 
   *work_items = NULL;
 
@@ -705,26 +732,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));
+           scratch_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;
@@ -980,6 +1023,7 @@ merge_text_file(svn_skel_t **work_items,
                     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);
@@ -1011,7 +1055,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 :
@@ -1193,11 +1239,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/atomic-revprop/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/props.c?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/props.c Fri Jul 23 19:37:19 2010
@@ -2197,22 +2197,12 @@ svn_wc__internal_propget(const svn_strin
 {
   apr_hash_t *prophash = NULL;
   enum svn_prop_kind kind = svn_property_kind(NULL, name);
-  svn_wc__db_kind_t wc_kind;
   svn_boolean_t hidden;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(kind != svn_prop_entry_kind);
 
-  SVN_ERR(svn_wc__db_read_kind(&wc_kind, db, local_abspath, TRUE, scratch_pool));
-
-  if (wc_kind == svn_wc__db_kind_unknown)
-    {
-      /* The node is not present, or not really "here". Therefore, the
-         property is not present.  */
-      *value = NULL;
-      return SVN_NO_ERROR;
-    }
-
+  /* This returns SVN_ERR_WC_PATH_NOT_FOUND for unversioned paths for us */
   SVN_ERR(svn_wc__db_node_hidden(&hidden, db, local_abspath, scratch_pool));
   if (hidden)
     {
@@ -2235,14 +2225,14 @@ svn_wc__internal_propget(const svn_strin
           svn_error_clear(err);
           return SVN_NO_ERROR;
         }
-      SVN_ERR_W(err, _("Failed to load properties from disk"));
+      SVN_ERR_W(err, _("Failed to load properties"));
     }
   else
     {
       /* regular prop */
       SVN_ERR_W(svn_wc__get_actual_props(&prophash, db, local_abspath,
                                          result_pool, scratch_pool),
-                _("Failed to load properties from disk"));
+                _("Failed to load properties"));
     }
 
   if (prophash)
@@ -2510,12 +2500,19 @@ svn_wc__internal_propset(svn_wc__db_t *d
                                              APR_HASH_KEY_STRING);
       apr_hash_t *old_keywords, *new_keywords;
 
-      SVN_ERR(svn_wc__get_keywords(&old_keywords, db, local_abspath,
-                                   old_value ? old_value->data : "",
-                                   scratch_pool, scratch_pool));
-      SVN_ERR(svn_wc__get_keywords(&new_keywords, db, local_abspath,
-                                   value ? value->data : "",
-                                   scratch_pool, scratch_pool));
+      if (old_value)
+        SVN_ERR(svn_wc__expand_keywords(&old_keywords,
+                                        db, local_abspath, old_value->data,
+                                        scratch_pool, scratch_pool));
+      else
+        old_keywords = apr_hash_make(scratch_pool);
+
+      if (value)
+        SVN_ERR(svn_wc__expand_keywords(&new_keywords,
+                                        db, local_abspath, value->data,
+                                        scratch_pool, scratch_pool));
+      else
+        new_keywords = apr_hash_make(scratch_pool);
 
       if (svn_subst_keywords_differ2(old_keywords, new_keywords, FALSE,
                                      scratch_pool))

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/questions.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/questions.c?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/questions.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/questions.c Fri Jul 23 19:37:19 2010
@@ -114,13 +114,11 @@ compare_and_verify(svn_boolean_t *modifi
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(versioned_file_abspath));
 
-  SVN_ERR(svn_wc__get_eol_style(&eol_style, &eol_str, db,
-                                versioned_file_abspath, scratch_pool,
-                                scratch_pool));
-  SVN_ERR(svn_wc__get_keywords(&keywords, db, versioned_file_abspath, NULL,
-                               scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__get_special(&special, db, versioned_file_abspath,
-                              scratch_pool));
+  SVN_ERR(svn_wc__get_translate_info(&eol_style, &eol_str,
+                                     &keywords,
+                                     &special,
+                                     db, versioned_file_abspath,
+                                     scratch_pool, scratch_pool));
 
   need_translation = svn_subst_translation_required(eol_style, eol_str,
                                                     keywords, special, TRUE);

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/status.c?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/status.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/status.c Fri Jul 23 19:37:19 2010
@@ -478,8 +478,10 @@ assemble_status(svn_wc_status3_t **statu
 
 #ifdef HAVE_SYMLINK
       if (has_props)
-        SVN_ERR(svn_wc__get_special(&wc_special, db, local_abspath,
-                                    scratch_pool));
+        SVN_ERR(svn_wc__get_translate_info(NULL, NULL, NULL,
+                                           &wc_special,
+                                           db, local_abspath,
+                                           scratch_pool, scratch_pool));
       else
         wc_special = FALSE;
 #endif /* HAVE_SYMLINK */
@@ -1128,6 +1130,7 @@ get_dir_status(const struct walk_status_
   svn_wc__db_status_t dir_status;
   svn_depth_t dir_depth;
   apr_pool_t *iterpool, *subpool = svn_pool_create(scratch_pool);
+  svn_error_t *err;
 
   /* See if someone wants to cancel this operation. */
   if (cancel_func)
@@ -1148,7 +1151,18 @@ get_dir_status(const struct walk_status_
     SVN_ERR(svn_hash_from_cstring_keys(&nodes, child_nodes, subpool));
   }
 
-  SVN_ERR(svn_io_get_dirents3(&dirents, local_abspath, FALSE, subpool, subpool));
+  err = svn_io_get_dirents3(&dirents, local_abspath, FALSE, subpool, subpool);
+#ifdef SVN_WC__SINGLE_DB
+  if (err
+      && (APR_STATUS_IS_ENOENT(err->apr_err)
+         || APR_STATUS_IS_ENODIR(err->apr_err)))
+    {
+      svn_error_clear(err);
+      dirents = apr_hash_make(subpool);
+    }
+  else
+#endif
+    SVN_ERR(err);
 
   SVN_ERR(svn_wc__db_read_info(&dir_status, NULL, NULL, &dir_repos_relpath,
                                &dir_repos_root_url, NULL, NULL, NULL, NULL,

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.c?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.c Fri Jul 23 19:37:19 2010
@@ -83,7 +83,11 @@ svn_wc__internal_translated_stream(svn_s
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
   SVN_ERR_ASSERT(svn_dirent_is_absolute(versioned_abspath));
 
-  SVN_ERR(svn_wc__get_special(&special, db, versioned_abspath, scratch_pool));
+  SVN_ERR(svn_wc__get_translate_info(&style, &eol,
+                                     &keywords,
+                                     &special,
+                                     db, versioned_abspath,
+                                     scratch_pool, scratch_pool));
 
   if (special)
     {
@@ -95,11 +99,6 @@ svn_wc__internal_translated_stream(svn_s
                                           scratch_pool);
     }
 
-  SVN_ERR(svn_wc__get_eol_style(&style, &eol, db, versioned_abspath,
-                                scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__get_keywords(&keywords, db, versioned_abspath, NULL,
-                               scratch_pool, scratch_pool));
-
   if (to_nf)
     SVN_ERR(svn_stream_open_readonly(stream, local_abspath, result_pool,
                                      scratch_pool));
@@ -170,11 +169,11 @@ svn_wc__internal_translated_file(const c
 
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(versioned_abspath));
-  SVN_ERR(svn_wc__get_eol_style(&style, &eol, db, versioned_abspath,
-                                scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__get_keywords(&keywords, db, versioned_abspath, NULL,
-                               scratch_pool, scratch_pool));
-  SVN_ERR(svn_wc__get_special(&special, db, versioned_abspath, scratch_pool));
+  SVN_ERR(svn_wc__get_translate_info(&style, &eol,
+                                     &keywords,
+                                     &special,
+                                     db, versioned_abspath,
+                                     scratch_pool, scratch_pool));
 
   if (! svn_subst_translation_required(style, eol, keywords, special, TRUE)
       && (! (flags & SVN_WC_TRANSLATE_FORCE_COPY)))
@@ -240,31 +239,6 @@ svn_wc__internal_translated_file(const c
   return SVN_NO_ERROR;
 }
 
-
-svn_error_t *
-svn_wc__get_eol_style(svn_subst_eol_style_t *style,
-                      const char **eol,
-                      svn_wc__db_t *db,
-                      const char *local_abspath,
-                      apr_pool_t *result_pool,
-                      apr_pool_t *scratch_pool)
-{
-  const svn_string_t *propval;
-
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-
-  /* Get the property value. */
-  SVN_ERR(svn_wc__internal_propget(&propval, db, local_abspath,
-                                   SVN_PROP_EOL_STYLE, result_pool,
-                                   scratch_pool));
-
-  /* Convert it. */
-  svn_subst_eol_style_from_value(style, eol, propval ? propval->data : NULL);
-
-  return SVN_NO_ERROR;
-}
-
-
 void
 svn_wc__eol_value_from_string(const char **value, const char *eol)
 {
@@ -280,56 +254,82 @@ svn_wc__eol_value_from_string(const char
     *value = NULL;
 }
 
-
 svn_error_t *
-svn_wc__get_keywords(apr_hash_t **keywords,
-                     svn_wc__db_t *db,
-                     const char *local_abspath,
-                     const char *force_list,
-                     apr_pool_t *result_pool,
-                     apr_pool_t *scratch_pool)
+svn_wc__get_translate_info(svn_subst_eol_style_t *style,
+                           const char **eol,
+                           apr_hash_t **keywords,
+                           svn_boolean_t *special,
+                           svn_wc__db_t *db,
+                           const char *local_abspath,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
 {
-  const char *list;
-  svn_revnum_t changed_rev;
-  apr_time_t changed_date;
-  const char *changed_author;
-  const char *url;
-
+  apr_hash_t *props;
+  svn_string_t *propval;
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  /* Choose a property list to parse:  either the one that came into
-     this function, or the one attached to PATH. */
-  if (force_list == NULL)
-    {
-      const svn_string_t *propval;
-
-      SVN_ERR(svn_wc__internal_propget(&propval, db, local_abspath,
-                                       SVN_PROP_KEYWORDS, scratch_pool,
-                                       scratch_pool));
+  SVN_ERR(svn_wc__get_actual_props(&props, db, local_abspath,
+                                   scratch_pool, scratch_pool));
 
-      /* The easy answer. */
-      if (propval == NULL)
-        {
-          *keywords = NULL;
-          return SVN_NO_ERROR;
-        }
+  if (eol)
+    {
+      propval = props ? apr_hash_get(props, SVN_PROP_EOL_STYLE,
+                                     APR_HASH_KEY_STRING) : NULL;
 
-      list = propval->data;
+      svn_subst_eol_style_from_value(style, eol, propval ? propval->data : NULL);
     }
-  else
-    list = force_list;
+
+  if (keywords)
+    {
+      propval = props ? apr_hash_get(props, SVN_PROP_KEYWORDS,
+                                     APR_HASH_KEY_STRING) : NULL;
+
+      if (!propval || propval->len == 0)
+        *keywords = NULL;
+      else
+        SVN_ERR(svn_wc__expand_keywords(keywords,
+                                        db, local_abspath,
+                                        propval->data,
+                                        result_pool, scratch_pool));
+    }
+  if (special)
+    {
+      propval = props ? apr_hash_get(props, SVN_PROP_SPECIAL,
+                                     APR_HASH_KEY_STRING) : NULL;
+
+      *special = (propval != NULL);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__expand_keywords(apr_hash_t **keywords,
+                        svn_wc__db_t *db,
+                        const char *local_abspath,
+                        const char *keyword_list,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool)
+{
+  svn_revnum_t changed_rev;
+  apr_time_t changed_date;
+  const char *changed_author;
+  const char *url;
 
   SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL,
                                NULL, NULL, &changed_rev,
-                               &changed_date, &changed_author, NULL, NULL,
+                               &changed_date, &changed_author, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL,
                                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                               db, local_abspath, scratch_pool, scratch_pool));
+                               NULL,
+                               db, local_abspath,
+                               scratch_pool, scratch_pool));
+
   SVN_ERR(svn_wc__internal_node_get_url(&url, db, local_abspath,
                                         scratch_pool, scratch_pool));
 
   SVN_ERR(svn_subst_build_keywords2(keywords,
-                                    list,
+                                    keyword_list,
                                     apr_psprintf(scratch_pool, "%ld",
                                                  changed_rev),
                                     url,
@@ -343,26 +343,6 @@ svn_wc__get_keywords(apr_hash_t **keywor
   return SVN_NO_ERROR;
 }
 
-
-svn_error_t *
-svn_wc__get_special(svn_boolean_t *special,
-                    svn_wc__db_t *db,
-                    const char *local_abspath,
-                    apr_pool_t *scratch_pool)
-{
-  const svn_string_t *propval;
-
-  /* Get the property value. */
-  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
-  SVN_ERR(svn_wc__internal_propget(&propval, db, local_abspath,
-                                   SVN_PROP_SPECIAL, scratch_pool,
-                                   scratch_pool));
-  *special = propval != NULL;
-
-  return SVN_NO_ERROR;
-}
-
-
 svn_error_t *
 svn_wc__maybe_set_executable(svn_boolean_t *did_set,
                              svn_wc__db_t *db,

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.h
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.h?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.h (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/translate.h Fri Jul 23 19:37:19 2010
@@ -36,8 +36,9 @@ extern "C" {
 
 /* Newline and keyword translation properties */
 
-/* Query the SVN_PROP_EOL_STYLE property on file LOCAL_ABSPATH in DB.  If
-   STYLE is non-null, set *STYLE to LOCAL_ABSPATH's eol style.  Set *EOL to
+/* If EOL is not-NULL query the SVN_PROP_EOL_STYLE property on file
+   LOCAL_ABSPATH in DB.  If STYLE is non-null, set *STYLE to LOCAL_ABSPATH's
+   eol style.  Set *EOL to
 
       - NULL for svn_subst_eol_style_none, or
 
@@ -50,15 +51,32 @@ extern "C" {
    If STYLE is null on entry, ignore it.  If *EOL is non-null on exit,
    it is a static string not allocated in POOL.
 
+   If KEYWORDS is not NULL Expand keywords for the file at LOCAL_ABSPATH
+   in DB, by parsing a whitespace-delimited list of keywords.  If any keywords
+   are found in the list, allocate *KEYWORDS from RESULT_POOL and populate it
+   with mappings from (const char *) keywords to their (svn_string_t *)
+   values (also allocated in RESULT_POOL).
+
+   If a keyword is in the list, but no corresponding value is
+   available, do not create a hash entry for it.  If no keywords are
+   found in the list, or if there is no list, set *KEYWORDS to NULL.
+
+   If SPECIAL is not NULL determine if the svn:special flag is set on LOCAL_ABSPATH
+   in DB.  If so, set SPECIAL to TRUE, if not, set it to FALSE
+
    Use SCRATCH_POOL for temporary allocation, RESULT_POOL for allocating
    *STYLE and *EOL.
 */
-svn_error_t *svn_wc__get_eol_style(svn_subst_eol_style_t *style,
-                                   const char **eol,
-                                   svn_wc__db_t *db,
-                                   const char *local_abspath,
-                                   apr_pool_t *result_pool,
-                                   apr_pool_t *scratch_pool);
+svn_error_t *
+svn_wc__get_translate_info(svn_subst_eol_style_t *style,
+                           const char **eol,
+                           apr_hash_t **keywords,
+                           svn_boolean_t *special,
+                           svn_wc__db_t *db,
+                           const char *local_abspath,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool);
+
 
 /* Reverse parser.  Given a real EOL string ("\n", "\r", or "\r\n"),
    return an encoded *VALUE ("LF", "CR", "CRLF") that one might see in
@@ -67,37 +85,26 @@ void svn_wc__eol_value_from_string(const
                                    const char *eol);
 
 /* Expand keywords for the file at LOCAL_ABSPATH in DB, by parsing a
-   whitespace-delimited list of keywords.  If any keywords are found
-   in the list, allocate *KEYWORDS from RESULT_POOL and populate it with
-   mappings from (const char *) keywords to their (svn_string_t *)
+   whitespace-delimited list of keywords KEYWORD_LIST.  If any keywords
+   are found in the list, allocate *KEYWORDS from RESULT_POOL and populate
+   it with mappings from (const char *) keywords to their (svn_string_t *)
    values (also allocated in RESULT_POOL).
 
    If a keyword is in the list, but no corresponding value is
    available, do not create a hash entry for it.  If no keywords are
    found in the list, or if there is no list, set *KEYWORDS to NULL.
 
-   If FORCE_LIST is non-null, use it as the list; else use the
-   SVN_PROP_KEYWORDS property for PATH.  In either case, use LOCAL_ABSPATH
-   to expand keyword values.
+   Use LOCAL_ABSPATH to expand keyword values.
 
    Use SCRATCH_POOL for any temporary allocations.
 */
-svn_error_t *svn_wc__get_keywords(apr_hash_t **keywords,
-                                  svn_wc__db_t *db,
-                                  const char *local_abspath,
-                                  const char *force_list,
-
-                                  apr_pool_t *result_pool,
-                                  apr_pool_t *scratch_pool);
-
-
-/* Determine if the svn:special flag is set on LOCAL_ABSPATH in DB.  If so,
-   set SPECIAL to TRUE, if not, set it to FALSE.  Perform any temporary
-   allocations in SCRATCH_POOL. */
-svn_error_t *svn_wc__get_special(svn_boolean_t *special,
-                                 svn_wc__db_t *db,
-                                 const char *local_abspath,
-                                 apr_pool_t *scratch_pool);
+svn_error_t *
+svn_wc__expand_keywords(apr_hash_t **keywords,
+                        svn_wc__db_t *db,
+                        const char *local_abspath,
+                        const char *keyword_list,
+                        apr_pool_t *result_pool,
+                        apr_pool_t *scratch_pool);
 
 /* If the SVN_PROP_EXECUTABLE property is present at all, then set
    LOCAL_ABSPATH in DB executable.  If DID_SET is non-null, then set

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/update_editor.c Fri Jul 23 19:37:19 2010
@@ -1029,7 +1029,9 @@ struct file_baton
 
   /* The last-changed-date of the file.  This is actually a property
      that comes through as an 'entry prop', and will be used to set
-     the working file's timestamp if it's added.  */
+     the working file's timestamp if it's added. 
+
+     Will be NULL unless eb->use_commit_times is TRUE. */
   const char *last_changed_date;
 
   /* Bump information for the directory this file lives in */
@@ -1204,7 +1206,7 @@ prep_directory(struct dir_baton *db,
   if (!locked_here)
     /* Recursive lock release on parent will release this lock. */
     SVN_ERR(svn_wc__acquire_write_lock(NULL, db->edit_baton->wc_ctx,
-                                       dir_abspath, pool, pool));
+                                       dir_abspath, FALSE, pool, pool));
 #endif
 
   return SVN_NO_ERROR;
@@ -2333,6 +2335,8 @@ add_directory(const char *path,
   svn_wc__db_status_t status;
   svn_wc__db_kind_t wc_kind;
   svn_boolean_t already_conflicted;
+  svn_boolean_t versioned_locally_and_present;
+  svn_wc_conflict_description2_t *tree_conflict = NULL;
   svn_error_t *err;
 
   /* Semantic check.  Either both "copyfrom" args are valid, or they're
@@ -2408,25 +2412,6 @@ add_directory(const char *path,
       db->ambient_depth = svn_depth_infinity;
     }
 
-  /* Is this path a conflict victim? */
-  SVN_ERR(node_already_conflicted(&already_conflicted, eb->db,
-                                  db->local_abspath, pool));
-  if (already_conflicted)
-    {
-      /* Record this conflict so that its descendants are skipped silently. */
-      SVN_ERR(remember_skipped_tree(eb, db->local_abspath));
-
-      db->skip_this = TRUE;
-      db->skip_descendants = TRUE;
-      db->already_notified = TRUE;
-
-      /* ### TODO: Also print victim_path in the skip msg. */
-      do_notification(eb, db->local_abspath, svn_node_unknown,
-                      svn_wc_notify_skip, pool);
-
-      return SVN_NO_ERROR;
-    }
-
   /* It may not be named the same as the administrative directory. */
   if (svn_wc_is_adm_dir(db->name, pool))
     return svn_error_createf(
@@ -2450,48 +2435,96 @@ add_directory(const char *path,
       svn_error_clear(err);
       wc_kind = svn_wc__db_kind_unknown;
       status = svn_wc__db_status_normal;
+
+      versioned_locally_and_present = FALSE;
     }
+  else
+    versioned_locally_and_present = IS_NODE_PRESENT(status);
 
-  /* The path can exist, but it must be a directory. */
-  if (kind == svn_node_file || kind == svn_node_unknown ||
-      (wc_kind != svn_wc__db_kind_unknown &&
-       wc_kind != svn_wc__db_kind_dir && IS_NODE_PRESENT(status)))
+  /* Is this path a conflict victim? */
+  SVN_ERR(node_already_conflicted(&already_conflicted, eb->db,
+                                  db->local_abspath, pool));
+  if (already_conflicted
+      && status == svn_wc__db_status_not_present
+      && kind == svn_node_none)
     {
-      db->already_notified = TRUE;
-      do_notification(eb, db->local_abspath, svn_node_dir,
-                      svn_wc_notify_update_obstruction, pool);
-
-      return svn_error_createf(
-       SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-       _("Failed to add directory '%s': a non-directory object of the "
-         "same name already exists"),
-       svn_dirent_local_style(db->local_abspath, pool));
+      /* A conflict is flagged. Now let's do some user convenience.
+       * When we flagged a tree conflict for a local unversioned node
+       * vs. an incoming add, and we find that this unversioned node is
+       * no longer in the way, automatically pull in the versioned node
+       * and remove the conflict marker.
+       * Right, the node status matches (not_present) and there is no
+       * unversioned obstruction in the file system (anymore?). If it
+       * has a tree conflict with reason 'unversioned', remove that. */
+      const svn_wc_conflict_description2_t *previous_tc;
+      SVN_ERR(svn_wc__get_tree_conflict(&previous_tc,
+                                        eb->wc_ctx,
+                                        db->local_abspath,
+                                        pool, pool));
+      if (previous_tc
+          && previous_tc->reason == svn_wc_conflict_reason_unversioned)
+        {
+          /* Remove tree conflict. */
+          SVN_ERR(svn_wc__db_op_set_tree_conflict(eb->db,
+                                                  db->local_abspath,
+                                                  NULL, pool));
+          /* Don't skip this path after all. */
+          already_conflicted = FALSE;
+        }
     }
 
-  if (kind == svn_node_dir &&
-      (wc_kind == svn_wc__db_kind_unknown || !IS_NODE_PRESENT(status)))
+  /* Now the "usual" behaviour if already conflicted. Skip it. */
+  if (already_conflicted)
     {
-      /* Found an unversioned directory */
-      db->obstruction_found = TRUE;
+      /* Record this conflict so that its descendants are skipped silently. */
+      SVN_ERR(remember_skipped_tree(eb, db->local_abspath));
 
-      if (!eb->allow_unver_obstructions)
-        {
-          db->already_notified = TRUE;
-          do_notification(eb, db->local_abspath, svn_node_dir,
-                          svn_wc_notify_update_obstruction, pool);
+      db->skip_this = TRUE;
+      db->skip_descendants = TRUE;
+      db->already_notified = TRUE;
 
-          return svn_error_createf(
-             SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-             _("Failed to add directory '%s': an unversioned "
-               "directory of the same name already exists"),
-             svn_dirent_local_style(db->local_abspath, pool));
-        }
+      /* ### TODO: Also print victim_path in the skip msg. */
+      do_notification(eb, db->local_abspath, svn_node_unknown,
+                      svn_wc_notify_skip, pool);
+      return SVN_NO_ERROR;
     }
-  else if (wc_kind == svn_wc__db_kind_dir)
+
+
+  if (versioned_locally_and_present)
     {
-      /* Directory exists */
-      if (IS_NODE_PRESENT(status) &&
-          status != svn_wc__db_status_deleted)
+      /* What to do with a versioned or schedule-add dir:
+
+         A dir already added without history is OK.  Set add_existed
+         so that user notification is delayed until after any prop
+         conflicts have been found.
+
+         An existing versioned dir is an error.  In the future we may
+         relax this restriction and simply update such dirs.
+
+         A dir added with history is a tree conflict. */
+
+      svn_boolean_t local_is_dir;
+      svn_boolean_t local_is_non_dir;
+      const char *local_is_copy = NULL;
+
+      /* Is the local add a copy? */
+      if (status == svn_wc__db_status_added)
+        SVN_ERR(svn_wc__node_get_copyfrom_info(&local_is_copy,
+                                               NULL, NULL, NULL, NULL,
+                                               eb->wc_ctx,
+                                               db->local_abspath,
+                                               pool, pool));
+
+
+      /* Is there something that is a file? */
+      local_is_dir = (wc_kind == svn_wc__db_kind_dir
+                      && status != svn_wc__db_status_deleted);
+
+      /* Is there *something* that is not a dir? */
+      local_is_non_dir = (wc_kind != svn_wc__db_kind_dir
+                          && status != svn_wc__db_status_deleted);
+
+      if (local_is_dir)
         {
           svn_boolean_t wc_root;
           svn_boolean_t switched;
@@ -2533,91 +2566,141 @@ add_directory(const char *path,
             }
         }
 
-      /* What to do with a versioned or schedule-add dir:
-
-         A dir already added without history is OK.  Set add_existed
-         so that user notification is delayed until after any prop
-         conflicts have been found.
+      /* We can't properly handle add vs. add with mismatching
+       * node kinds before single db. */
+      if (local_is_non_dir)
+        {
+          db->already_notified = TRUE;
+          do_notification(eb, db->local_abspath, svn_node_dir,
+                          svn_wc_notify_update_obstruction, pool);
+          return svn_error_createf(
+                   SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+                   _("Failed to add directory '%s': a non-directory object "
+                     "of the same name already exists"),
+                   svn_dirent_local_style(db->local_abspath,
+                                          pool));
+        }
 
-         An existing versioned dir is an error.  In the future we may
-         relax this restriction and simply update such dirs.
+      /* Do tree conflict checking if
+       *  - if there is a local copy.
+       *  - if this is a switch operation
+       *  - the node kinds mismatch (when single db is here)
+       *
+       * During switch, local adds at the same path as incoming adds get
+       * "lost" in that switching back to the original will no longer have the
+       * local add. So switch always alerts the user with a tree conflict.
+       *
+       * Allow pulling absent/exluded/not_present nodes back in.
+       *
+       * ### This code is already gearing up to single db with respect to
+       * add-vs.-add conflicts with mismatching node kinds. But before single
+       * db, we cannot deal with mismatching node kinds properly.
+       *
+       * ### We would also like to be checking copyfrom infos to not flag tree
+       * conflicts on two copies with identical history. But at the time of
+       * writing, add_directory() does not get any copyfrom information. */
+      if (! pb->in_deleted_and_tree_conflicted_subtree
+          && (eb->switch_relpath != NULL
+              || local_is_non_dir
+              || local_is_copy
+             )
+         )
+        {
+          SVN_ERR(check_tree_conflict(&tree_conflict, eb,
+                                      db->local_abspath,
+                                      svn_wc_conflict_action_add,
+                                      svn_node_dir, db->new_relpath, pool));
+        }
 
-         A dir added with history is a tree conflict. */
 
-      if (status == svn_wc__db_status_added)
+      if (tree_conflict == NULL)
         {
-          /* Specialize the added case to added, copied, moved */
-          SVN_ERR(svn_wc__db_scan_addition(&status, NULL, NULL, NULL, NULL,
-                                           NULL, NULL, NULL, NULL, eb->db,
-                                           db->local_abspath, pool, pool));
+          /* We have a node in WORKING and we've decided not to flag a
+           * conflict, so merge it with the incoming add. */
+          db->add_existed = TRUE;
+
+          /* Pre-single-db, a dir that was OS-deleted from the working copy
+           * along with its .svn folder is seen 'obstructed' in this code
+           * path. The particular situation however better matches the word
+           * 'missing'. We do add_existed to avoid spurious errors where other
+           * code relies on add_existed to be TRUE when there is a node
+           * record (schedule_tests delete_redelete_fudgery used to XFail).
+           * Still, let's notify 'A' as the old client did. Ultimately, this
+           * should probably say 'Restored' instead of 'A', like with file. */
+          if (status == svn_wc__db_status_obstructed
+              || status == svn_wc__db_status_obstructed_add
+              || status == svn_wc__db_status_obstructed_delete)
+            {
+              db->already_notified = TRUE;
+              do_notification(eb, db->local_abspath, svn_node_dir,
+                              svn_wc_notify_add, pool);
+            }
         }
+    }
+  else if (kind != svn_node_none)
+    {
+      /* There's an unversioned node at this path. */
+      db->obstruction_found = TRUE;
 
-      switch (status)
+      /* Unversioned, obstructing dirs are handled by prop merge/conflict,
+       * if unversioned obstructions are allowed. */
+      if (! (kind == svn_node_dir && eb->allow_unver_obstructions))
         {
-          case svn_wc__db_status_absent:
-          case svn_wc__db_status_excluded:
-            /* Ignore these hidden states. Allow pulling them (back) in. */
-            break;
-          case svn_wc__db_status_not_present:
-            break;
-          case svn_wc__db_status_obstructed:
-          case svn_wc__db_status_obstructed_add:
-          case svn_wc__db_status_obstructed_delete:
-            /* ### In 1.6 we ignored these cases in this block as
-                   the behavior was just pulling them back in.
+          /* ### Instead of skipping, this should bring in the BASE node
+           * and mark some sort of obstruction-conflict. Come, o single-db! */
+          db->skip_this = TRUE;
 
-                   Explicitly handle them as not raising a tree conflict
-                   now. Will never occur once we have a central DB. */
-            break;
-          case svn_wc__db_status_added:
-            /* ### BH: I think this case should be conditional with something
-                       like allow_unver_obstructions, as this changes the
-                       base of locally added files.
-               ### BH: Always generate tree conflict? */
-            db->add_existed = TRUE;
-            break;
-          default:
-            {
-              svn_wc_conflict_description2_t *tree_conflict = NULL;
+          /* If we are skipping an add, we need to tell the WC that
+           * there's a node supposed to be here which we don't have. */
+          SVN_ERR(svn_wc__db_base_add_absent_node(eb->db, db->local_abspath,
+                                                  db->new_relpath,
+                                                  eb->repos_root,
+                                                  eb->repos_uuid,
+                                                  (eb->target_revision?
+                                                   *eb->target_revision
+                                                   : SVN_INVALID_REVNUM),
+                                                  svn_wc__db_kind_dir,
+                                                  svn_wc__db_status_not_present,
+                                                  NULL, NULL, pool));
+          SVN_ERR(remember_skipped_tree(eb, db->local_abspath));
+
+          /* Mark a conflict */
+          SVN_ERR(create_tree_conflict(&tree_conflict, eb,
+                                       db->local_abspath,
+                                       svn_wc_conflict_reason_unversioned,
+                                       svn_wc_conflict_action_add,
+                                       svn_node_dir,
+                                       db->new_relpath, pool, pool));
+          SVN_ERR_ASSERT(tree_conflict != NULL);
+        }
+    }
 
-              /* Check for conflicts only when we haven't already recorded
-               * a tree-conflict on a parent node. */
-              if (!db->in_deleted_and_tree_conflicted_subtree)
-                SVN_ERR(check_tree_conflict(&tree_conflict, eb,
-                                            db->local_abspath,
-                                            svn_wc_conflict_action_add,
-                                            svn_node_dir, db->new_relpath, pool));
+  if (tree_conflict != NULL)
+    {
+      svn_skel_t *work_item;
 
-              if (tree_conflict != NULL)
-                {
-                  svn_skel_t *work_item;
+      /* Queue this conflict in the parent so that its descendants
+         are skipped silently. */
+      SVN_ERR(svn_wc__loggy_add_tree_conflict(&work_item,
+                                              eb->db,
+                                              pb->local_abspath,
+                                              tree_conflict,
+                                              pool));
+      SVN_ERR(svn_wc__db_wq_add(eb->db, pb->local_abspath,
+                                work_item, pool));
 
-                  /* Queue this conflict in the parent so that its descendants
-                     are skipped silently. */
-                  SVN_ERR(svn_wc__loggy_add_tree_conflict(&work_item,
-                                                          eb->db,
-                                                          pb->local_abspath,
-                                                          tree_conflict,
-                                                          pool));
-                  SVN_ERR(svn_wc__db_wq_add(eb->db, pb->local_abspath,
-                                            work_item, pool));
-
-                  SVN_ERR(remember_skipped_tree(eb, db->local_abspath));
-
-                  db->skip_this = TRUE;
-                  db->skip_descendants = TRUE;
-                  db->already_notified = TRUE;
+      SVN_ERR(remember_skipped_tree(eb, db->local_abspath));
 
-                  do_notification(eb, db->local_abspath, svn_node_unknown,
-                                  svn_wc_notify_tree_conflict, pool);
+      db->skip_this = TRUE;
+      db->skip_descendants = TRUE;
+      db->already_notified = TRUE;
 
-                  return SVN_NO_ERROR;
-                }
-            }
-            break;
-        }
+      do_notification(eb, db->local_abspath, svn_node_unknown,
+                      svn_wc_notify_tree_conflict, pool);
+      return SVN_NO_ERROR;
     }
 
+
 #ifdef SINGLE_DB
   SVN_ERR(svn_wc__db_temp_op_set_new_dir_to_incomplete(eb->db,
                                                        db->local_abspath,
@@ -4429,7 +4512,7 @@ static svn_error_t *
 change_file_prop(void *file_baton,
                  const char *name,
                  const svn_string_t *value,
-                 apr_pool_t *pool)
+                 apr_pool_t *scratch_pool)
 {
   struct file_baton *fb = file_baton;
   struct edit_baton *eb = fb->edit_baton;
@@ -4446,10 +4529,13 @@ change_file_prop(void *file_baton,
   /* Special case: If use-commit-times config variable is set we
      cache the last-changed-date propval so we can use it to set
      the working file's timestamp. */
-  if (eb->use_commit_times
-      && (strcmp(name, SVN_PROP_ENTRY_COMMITTED_DATE) == 0)
-      && value)
-    fb->last_changed_date = apr_pstrdup(fb->pool, value->data);
+  if (value
+      && eb->use_commit_times
+      && (strcmp(name, SVN_PROP_ENTRY_COMMITTED_DATE) == 0))
+    {
+      /* propchange is already in the right pool */
+      fb->last_changed_date = propchange->value->data;
+    }
 
   return SVN_NO_ERROR;
 }
@@ -4606,7 +4692,7 @@ merge_file(svn_skel_t **work_items,
                                                FALSE /* compare_textbases */,
                                                pool));
     }
-  else if (new_text_base_sha1_checksum)
+  else if (new_text_base_sha1_checksum && !fb->obstruction_found)
     {
       svn_stream_t *pristine_stream;
 
@@ -4624,8 +4710,13 @@ merge_file(svn_skel_t **work_items,
     }
   else
     {
-      /* No other potential changes, so the working file is NOT modified.  */
-      is_locally_modified = FALSE;
+      /* No other potential changes, so the working file is NOT modified.
+         Except when we have a local obstruction! */
+
+      if (fb->obstruction_found)
+        is_locally_modified = TRUE;
+      else
+        is_locally_modified = FALSE;
     }
 
   if (have_base)
@@ -4843,8 +4934,11 @@ merge_file(svn_skel_t **work_items,
 
       apr_hash_t *keywords;
 
-      SVN_ERR(svn_wc__get_keywords(&keywords, eb->db, fb->local_abspath, NULL,
-                                   pool, pool));
+      SVN_ERR(svn_wc__get_translate_info(NULL, NULL,
+                                         &keywords,
+                                         NULL,
+                                         eb->db, fb->local_abspath,
+                                         pool, pool));
       if (magic_props_changed || keywords)
         {
           /* Special edge-case: it's possible that this file installation
@@ -4885,22 +4979,28 @@ merge_file(svn_skel_t **work_items,
       && !is_locally_modified
       && (fb->adding_file || status == svn_wc__db_status_normal))
     {
+      apr_time_t set_date = 0;
       /* Adjust working copy file unless this file is an allowed
          obstruction. */
       if (fb->last_changed_date && !fb->obstruction_found)
         {
-          SVN_ERR(svn_wc__loggy_set_timestamp(
-                    &work_item, eb->db, pb->local_abspath,
-                    fb->local_abspath, fb->last_changed_date,
-                    pool));
-          *work_items = svn_wc__wq_merge(*work_items, work_item, pool);
+          /* Ignore invalid dates */
+          err = svn_time_from_cstring(&set_date, fb->last_changed_date,
+                                      pool);
+
+          if (err)
+            {
+              svn_error_clear(err);
+              set_date = 0;
+            }
         }
 
-      /* ### what if the file is locally-deleted? or if there is an
-         ### obstruction. OP_RECORD_FILEINFO will deal with a missing
-         ### file, but what if this is NOT our file? (ie. obstruction)  */
+      /* If this would have been an obstruction, we wouldn't be here,
+         because we would have installed an obstruction or tree conflict
+         instead */
       SVN_ERR(svn_wc__wq_build_record_fileinfo(&work_item,
                                                fb->local_abspath,
+                                               set_date,
                                                pool));
       *work_items = svn_wc__wq_merge(*work_items, work_item, pool);
     }

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/upgrade.c?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/upgrade.c (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/upgrade.c Fri Jul 23 19:37:19 2010
@@ -90,20 +90,33 @@ read_propfile(apr_hash_t **props,
 {
   svn_error_t *err;
   svn_stream_t *stream;
+  apr_finfo_t finfo;
 
-  err = svn_stream_open_readonly(&stream, propfile_abspath,
-                                 scratch_pool, scratch_pool);
-  if (err)
-    {
-      if (!APR_STATUS_IS_ENOENT(err->apr_err))
-        return svn_error_return(err);
+  err = svn_io_stat(&finfo, propfile_abspath, APR_FINFO_SIZE, scratch_pool);
 
+  if (err
+      && (APR_STATUS_IS_ENOENT(err->apr_err)
+          || APR_STATUS_IS_ENOTDIR(err->apr_err)))
+    {
       svn_error_clear(err);
 
       /* The propfile was not there. Signal with a NULL.  */
       *props = NULL;
       return SVN_NO_ERROR;
     }
+  else
+    SVN_ERR(err);
+
+  /* A 0-bytes file signals an empty property list.
+     (mostly used for revert-props) */
+  if (finfo.size == 0)
+    {
+      *props = apr_hash_make(result_pool);
+      return SVN_NO_ERROR;
+    }
+
+  SVN_ERR(svn_stream_open_readonly(&stream, propfile_abspath,
+                                   scratch_pool, scratch_pool));
 
   /* ### does this function need to be smarter? will we see zero-length
      ### files? see props.c::load_props(). there may be more work here.
@@ -468,16 +481,14 @@ wipe_obsolete_files(const char *wcroot_a
                                       scratch_pool),
                     TRUE, scratch_pool));
 
-#if (SVN_WC__VERSION >= 17)
   /* Remove the old text-base directory and the old text-base files. */
   svn_error_clear(svn_io_remove_dir2(
                     svn_wc__adm_child(wcroot_abspath,
                                       TEXT_BASE_SUBDIR,
                                       scratch_pool),
                     FALSE, NULL, NULL, scratch_pool));
-#endif
 
-#if 0  /* ### NOT READY TO WIPE THESE FILES!!  */
+#if (SVN_WC__VERSION >= 18)
   /* Remove the old properties files... whole directories at a time.  */
   svn_error_clear(svn_io_remove_dir2(
                     svn_wc__adm_child(wcroot_abspath,
@@ -964,7 +975,7 @@ migrate_node_props(const char *wcroot_ab
                         scratch_pool, scratch_pool));
 
   return svn_error_return(svn_wc__db_upgrade_apply_props(
-                            sdb, name,
+                            sdb, wcroot_abspath, name,
                             base_props, revert_props, working_props,
                             original_format,
                             scratch_pool));
@@ -1338,20 +1349,17 @@ upgrade_to_wcng(svn_wc__db_t *db,
       SVN_ERR(svn_wc__db_upgrade_apply_dav_cache(sdb, all_wcprops, iterpool));
     }
 
+  SVN_ERR(migrate_text_bases(dir_abspath, sdb, iterpool));
+
+#if (SVN_WC__VERSION >= 18)
   /* Upgrade all the properties (including "this dir").
 
      Note: this must come AFTER the entries have been migrated into the
      database. The upgrade process needs the children in BASE_NODE and
      WORKING_NODE, and to examine the resultant WORKING state.  */
-#if 0
-  /* ### not quite yet  */
   SVN_ERR(migrate_props(dir_abspath, sdb, old_format, iterpool));
 #endif
 
-#if (SVN_WC__VERSION >= 17)
-  SVN_ERR(migrate_text_bases(dir_abspath, sdb, iterpool));
-#endif
-
   /* All done. DB should finalize the upgrade process now.  */
   SVN_ERR(svn_wc__db_upgrade_finish(dir_abspath, sdb, iterpool));
 

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-metadata.sql Fri Jul 23 19:37:19 2010
@@ -479,6 +479,137 @@ PRAGMA user_version =
 -- define: SVN_WC__VERSION
 ;
 
+/* ------------------------------------------------------------------------- */
+
+/* The NODE_DATA table describes the way WORKING nodes are layered on top of
+   BASE nodes and on top of other WORKING nodes, due to nested tree structure
+   changes. The layers are modelled using the "op_depth" column.
+
+   Each row in BASE_NODE has an associated row NODE_DATA. Additionally, each
+   row in WORKING_NODE has one or more associated rows in NODE_DATA.
+
+   This table contains only those data elements which apply to BASE as well as
+   all WORKING layers; fields applicable only to the currently visible WORKING
+   node or BASE node are located in the WORKING_NODE and BASE_NODE tables.
+
+   ### This table is to be integrated into the SCHEMA statement as soon
+       the experimental status of NODE_DATA is lifted.
+
+   For illustration, with a scenario like this:
+
+     # (0)
+     svn rm foo
+     svn cp ^/moo foo   # (1)
+     svn rm foo/bar
+     touch foo/bar
+     svn add foo/bar    # (2)
+
+   , these are the NODE_DATA for the path foo/bar (before single-db, the
+   numbering of op_depth is still a bit different):
+   
+   (0)  BASE_NODE ----->  NODE_DATA (op_depth == 0)
+   (1)                    NODE_DATA (op_depth == 1) ( <----_ )
+   (2)                    NODE_DATA (op_depth == 2)   <----- WORKING_NODE
+   
+   0 is the original data for foo/bar before 'svn rm foo' (if it existed).
+   1 is the data for foo/bar copied in from ^/moo/bar. (There would also be a
+     WORKING_NODE for the path foo, with original_* pointing at ^/moo.)
+   2 is the to-be-committed data for foo/bar, created by 'svn add foo/bar'.
+
+   An 'svn revert foo/bar' would remove the NODE_DATA of (2) (and possibly 
+   rewire the WORKING_NODE to represent a child of the operation (1)).
+   So foo/bar would be a copy of ^/moo/bar again.
+ */
+-- STMT_CREATE_NODE_DATA
+CREATE TABLE NODE_DATA (
+  wc_id  INTEGER NOT NULL REFERENCES WCROOT (id),
+  local_relpath  TEXT NOT NULL,
+  op_depth INTEGER NOT NULL,
+
+  /* parent's local_relpath for aggregating children of a given parent.
+     this will be "" if the parent is the wcroot.  Since a wcroot will
+     never have a WORKING node the parent_relpath will never be null. */
+  /* ### would be nice to make this column NOT NULL.  */
+  parent_relpath  TEXT,
+
+  /* In case 'op_depth' is equal to 0, this is part of the BASE tree; in
+     that case, all presence values except 'base-deleted' are allowed.
+
+
+     In case 'op_depth' is greater than 0, this is part of a layer of
+     working nodes; in that case, the following presence values apply:
+
+     Is this node "present" or has it been excluded for some reason?
+     Only allowed values: normal, not-present, incomplete, base-deleted.
+     (the others do not make sense for the WORKING tree)
+
+     normal: this node has been added/copied/moved-here. There may be an
+       underlying BASE node at this location, implying this is a replace.
+       Scan upwards from here looking for copyfrom or moved_here values
+       to detect the type of operation constructing this node.
+
+     not-present: the node (or parent) was originally copied or moved-here.
+       A subtree of that source has since been deleted. There may be
+       underlying BASE node to replace. For a move-here or copy-here, the
+       records are simply removed rather than switched to not-present.
+       Note this reflects a deletion only. It is not possible move-away
+       nodes from the WORKING tree. The purported destination would receive
+       a copy from the original source of a copy-here/move-here, or if the
+       nodes were plain adds, those nodes would be shifted to that target
+       for addition.
+
+     incomplete: nodes are being added into the WORKING tree, and the full
+       information about this node is not (yet) present.
+
+     base-deleted: the underlying BASE node has been marked for deletion due
+       to a delete or a move-away (see the moved_to column to determine
+       which), and has not been replaced.  */
+  presence  TEXT NOT NULL,
+
+  /* the kind of the new node. may be "unknown" if the node is not present. */
+  kind  TEXT NOT NULL,
+
+  /* If this node was moved here or copied here, then the following fields may
+     have information about their source node. See BASE_NODE.changed_* for
+     more information.
+
+     For an added or not-present node, these are null.  */
+  changed_revision  INTEGER,
+  changed_date      INTEGER,  /* an APR date/time (usec since 1970) */
+  changed_author    TEXT,
+
+  /* NULL depth means "default" (typically svn_depth_infinity) */
+  /* ### depth on WORKING? seems this is a BASE-only concept. how do
+     ### you do "files" on an added-directory? can't really ignore
+     ### the subdirs! */
+  /* ### maybe a WC-to-WC copy can retain a depth?  */
+  depth  TEXT,
+
+  /* The SHA-1 checksum of the pristine text, if this node is a file and was
+     moved here or copied here, else NULL. */
+  checksum  TEXT,
+
+  /* for kind==symlink, this specifies the target. */
+  symlink_target  TEXT,
+
+  /* Where this node was copied/moved from. All copyfrom_* fields are set
+     only on the root of the operation, and are NULL for all children. */
+  original_repos_id  INTEGER REFERENCES REPOSITORY (id),
+  original_repos_path  TEXT,
+  original_revision  INTEGER,
+
+  /* serialized skel of this node's properties. NULL if we
+     have no information about the properties (a non-present node). */
+  properties  BLOB,
+
+  PRIMARY KEY (wc_id, local_relpath, op_depth)
+
+  );
+
+CREATE INDEX I_NODE_PARENT ON NODE_DATA (wc_id, parent_relpath);
+CREATE INDEX I_NODE_PATH ON NODE_DATA (wc_id, local_relpath);
+
+
 
 /* ------------------------------------------------------------------------- */
 

Modified: subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql?rev=967221&r1=967220&r2=967221&view=diff
==============================================================================
--- subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/atomic-revprop/subversion/libsvn_wc/wc-queries.sql Fri Jul 23 19:37:19 2010
@@ -77,6 +77,15 @@ insert or replace into base_node (
 values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
         ?15, ?16, ?17);
 
+-- STMT_INSERT_NODE_DATA
+insert or replace into node_data (
+   wc_id, local_relpath, op_depth, parent_relpath, presence, kind,
+   changed_revision, changed_date, changed_author, depth, checksum,
+   symlink_target, original_repos_id, original_repos_path,
+   original_revision, properties)
+values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12,
+        ?13, ?14, ?15, ?16);
+
 -- STMT_INSERT_BASE_NODE_INCOMPLETE
 insert or ignore into base_node (
   wc_id, local_relpath, parent_relpath, presence, kind, revnum)
@@ -93,6 +102,11 @@ INSERT OR IGNORE INTO WORKING_NODE (
   wc_id, local_relpath, parent_relpath, presence, kind)
 VALUES (?1, ?2, ?3, 'incomplete', 'unknown');
 
+-- STMT_INSERT_NODE_DATA_INCOMPLETE
+INSERT OR IGNORE INTO NODE_DATA (
+  wc_id, local_relpath, op_depth, parent_relpath, presence, kind)
+VALUES (?1, ?2, ?3, ?4, 'incomplete', 'unknown');
+
 -- STMT_COUNT_BASE_NODE_CHILDREN
 SELECT COUNT(*) FROM BASE_NODE
 WHERE wc_id = ?1 AND parent_relpath = ?2;
@@ -133,10 +147,21 @@ where wc_id = ?1 and local_relpath = ?2;
 update base_node set properties = ?3
 where wc_id = ?1 and local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_DATA_BASE_PROPS
+update node_data set properties = ?3
+where wc_id = ?1 and local_relpath = ?2 and op_depth = 0;
+
 -- STMT_UPDATE_WORKING_PROPS
 update working_node set properties = ?3
 where wc_id = ?1 and local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_DATA_WORKING_PROPS
+update node_data set properties = ?3
+where wc_id = ?1 and local_relpath = ?2
+  and op_depth in
+   (select max(op_depth) from node_data
+    where wc_id = ?1 and local_relpath = ?2);
+
 -- STMT_UPDATE_ACTUAL_PROPS
 update actual_node set properties = ?3
 where wc_id = ?1 and local_relpath = ?2;
@@ -196,6 +221,12 @@ where copyfrom_repos_id is not null and 
   (local_relpath = ?2 or
    local_relpath like ?3 escape '#');
 
+-- STMT_UPDATE_NODE_DATA_RECURSIVE_ORIGINAL_REPO
+update node_data set original_repos_id = ?5
+where wc_id = ?1 and original_repos_id = ?4 and
+  (local_relpath = ?2 or
+   local_relpath like ?3 escape '#');
+
 -- STMT_UPDATE_LOCK_REPOS_ID
 update lock set repos_id = ?4
 where repos_id = ?1 and
@@ -259,10 +290,26 @@ VALUES (?1, ?2, ?3, ?4);
 delete from base_node
 where wc_id = ?1 and local_relpath = ?2;
 
+/* ### Basically, this query can't exist:
+   we can't be deleting BASE nodes while they still have
+   associated WORKING nodes;
+   at minimum, the op_depth restriction should be removed */
+-- STMT_DELETE_NODE_DATA_BASE
+delete from node_data
+where wc_id = ?1 and local_relpath = ?2 and op_depth = 0;
+
 -- STMT_DELETE_WORKING_NODE
 delete from working_node
 where wc_id = ?1 and local_relpath = ?2;
 
+-- STMT_DELETE_NODE_DATA_WORKING
+delete from node_data
+where wc_id = ?1 and local_relpath = ?2 and op_depth > 0;
+
+-- STMT_DELETE_NODE_DATA_LAYERS
+delete from node_data
+where wc_id = ?1 and local_relpath = ?2 and op_depth >= ?3;
+
 -- STMT_DELETE_ACTUAL_NODE
 delete from actual_node
 where wc_id = ?1 and local_relpath = ?2;
@@ -271,30 +318,66 @@ where wc_id = ?1 and local_relpath = ?2;
 UPDATE BASE_NODE SET depth = ?3
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_BASE_DEPTH
+UPDATE NODE_DATA SET depth = ?3
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
+
 -- STMT_UPDATE_WORKING_DEPTH
 UPDATE WORKING_NODE SET depth = ?3
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_WORKING_DEPTH
+UPDATE NODE_DATA SET depth = ?3
+WHERE wc_id = ?1 AND local_relpath = ?2 AND
+      op_depth IN (SELECT MAX(op_depth) FROM NODE_DATA
+                   WHERE wc_id = ?1 AND local_relpath = ?2);
+
 -- STMT_UPDATE_BASE_EXCLUDED
-UPDATE BASE_NODE SET presence = 'excluded', depth = 'infinity'
+UPDATE BASE_NODE SET presence = 'excluded', depth = NULL
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_BASE_EXCLUDED
+UPDATE NODE_DATA SET presence = 'excluded', depth = NULL
+WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = 0;
+
 -- STMT_UPDATE_WORKING_EXCLUDED
-UPDATE WORKING_NODE SET presence = 'excluded', depth = 'infinity'
+UPDATE WORKING_NODE SET presence = 'excluded', depth = NULL
 WHERE wc_id = ?1 AND local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_WORKING_EXCLUDED
+UPDATE NODE_DATA SET presence = 'excluded', depth = NULL
+WHERE wc_id = ?1 AND local_relpath = ?2 AND
+      op_depth IN (SELECT MAX(op_depth) FROM NODE_DATA
+                   WHERE wc_id = ?1 AND local_relpath = ?2);
+
 -- STMT_UPDATE_BASE_PRESENCE
 update base_node set presence= ?3
 where wc_id = ?1 and local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_BASE_PRESENCE
+update node_data set presence = ?3
+where wc_id = ?1 and local_relpath = ?2 and op_depth = 0;
+
 -- STMT_UPDATE_BASE_PRESENCE_KIND
 update base_node set presence = ?3, kind = ?4
 where wc_id = ?1 and local_relpath = ?2;
 
+-- STMT_UPDATE_NODE_BASE_PRESENCE_KIND
+update node_data set presence = ?3, kind = ?4
+where wc_id = ?1 and local_relpath = ?2 and op_depth = 0;
+
 -- STMT_UPDATE_WORKING_PRESENCE
 update working_node set presence = ?3
 where wc_id = ?1 and local_relpath =?2;
 
+-- STMT_UPDATE_NODE_WORKING_PRESENCE
+update node_data set presence = ?3
+where wc_id = ?1 and local_relpath = ?2
+  and op_depth in (select op_depth from node_data
+                   where wc_id = ?1 and local_relpath = ?2
+                   order by op_depth desc
+                   limit 1);
+
 -- STMT_UPDATE_BASE_PRESENCE_AND_REVNUM
 update base_node set presence = ?3, revnum = ?4
 where wc_id = ?1 and local_relpath = ?2;
@@ -581,8 +664,8 @@ SELECT local_relpath FROM WORKING_NODE
 WHERE kind = 'file';
 
 -- STMT_PLAN_PROP_UPGRADE
-SELECT 0, null, wc_id FROM BASE_NODE WHERE local_relpath = ?1
-UNION
+SELECT 0, presence, wc_id FROM BASE_NODE WHERE local_relpath = ?1
+UNION ALL
 SELECT 1, presence, wc_id FROM WORKING_NODE WHERE local_relpath = ?1;
 
 -- STMT_ATTACH_WCROOT_DB