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/03/30 22:58:01 UTC

svn commit: r929279 [17/20] - in /subversion/branches/svn-patch-improvements: ./ build/ac-macros/ build/generator/ build/generator/templates/ contrib/client-side/emacs/ notes/feedback/ notes/meetings/ notes/wc-ng/ subversion/ subversion/bindings/javahl...

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.c Tue Mar 30 20:57:53 2010
@@ -37,7 +37,6 @@
 #include "adm_files.h"
 #include "translate.h"
 #include "log.h"
-#include "lock.h"  /* for svn_wc__adm_available  */
 
 #include "svn_private_config.h"
 #include "private/svn_skel.h"
@@ -54,9 +53,14 @@
 #define OP_KILLME "killme"
 #define OP_LOGGY "loggy"
 #define OP_DELETION_POSTCOMMIT "deletion-postcommit"
+/* Arguments of OP_POSTCOMMIT:
+ *   (local_abspath, revnum, date, [author], [checksum],
+ *    [dav_cache/wc_props], keep_changelist, [tmp_text_base_abspath]). */
 #define OP_POSTCOMMIT "postcommit"
 #define OP_INSTALL_PROPERTIES "install-properties"
 #define OP_DELETE "delete"
+#define OP_FILE_INSTALL "file-install"
+#define OP_FILE_REMOVE "file-remove"
 
 
 struct work_item_dispatch {
@@ -117,6 +121,9 @@ copy_and_translate(svn_wc__db_t *db,
 }
 
 
+/* If SOURCE_ABSPATH is present, then move it to DEST_ABSPATH. Ignore any
+   ENOENT message for a missing source, which may indicate the move has
+   already been performed.  */
 static svn_error_t *
 move_if_present(const char *source_abspath,
                 const char *dest_abspath,
@@ -167,6 +174,9 @@ maybe_remove_conflict(const char *parent
 }
 
 
+/* Process the OP_REVERT work item WORK_ITEM.
+ * See svn_wc__wq_add_revert() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_revert(svn_wc__db_t *db,
            const svn_skel_t *work_item,
@@ -216,8 +226,14 @@ run_revert(svn_wc__db_t *db,
       SVN_ERR(move_if_present(revert_props_path, base_props_path,
                               scratch_pool));
 
-      SVN_ERR(svn_wc__db_temp_op_set_pristine_props(db, local_abspath, NULL,
-                                                    TRUE, scratch_pool));
+      /* ### we should also be setting BASE props. and really... we shouldn't
+         ### even bother zero-ing out these props. the WORKING node should
+         ### be disappearing after a revert.  */
+#if 0
+      SVN_ERR(svn_wc__db_temp_working_set_props(db, local_abspath,
+                                                apr_hash_make(scratch_pool),
+                                                scratch_pool));
+#endif
     }
 
   /* The "working" props contain changes. Nuke 'em from orbit.  */
@@ -614,6 +630,9 @@ svn_wc__wq_add_revert(svn_boolean_t *wil
 /* OP_PREPARE_REVERT_FILES  */
 
 
+/* Process the OP_PREPARE_REVERT_FILES work item WORK_ITEM.
+ * See svn_wc__wq_prepare_revert_files() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_prepare_revert_files(svn_wc__db_t *db,
                          const svn_skel_t *work_item,
@@ -672,10 +691,14 @@ run_prepare_revert_files(svn_wc__db_t *d
                                         scratch_pool));
     }
 
-  /* Stop intheriting BASE_NODE properties */
-  SVN_ERR(svn_wc__db_temp_op_set_pristine_props(db, local_abspath,
-                                                apr_hash_make(scratch_pool),
-                                                TRUE, scratch_pool));
+  /* Put some blank properties into the WORKING node.  */
+  /* ### this seems bogus. something else should come along and put the
+     ### correct values in here. we shouldn't put empty values in.  */
+#if 0
+  SVN_ERR(svn_wc__db_temp_working_set_props(db, local_abspath,
+                                            apr_hash_make(scratch_pool),
+                                            scratch_pool));
+#endif
 
   return SVN_NO_ERROR;
 }
@@ -704,6 +727,9 @@ svn_wc__wq_prepare_revert_files(svn_wc__
 /* OP_REMOVE_REVERT_FILES  */
 
 
+/* Process the OP_REMOVE_REVERT_FILES work item WORK_ITEM.
+ * See svn_wc__wq_remove_revert_files() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_remove_revert_files(svn_wc__db_t *db,
                         const svn_skel_t *work_item,
@@ -715,7 +741,7 @@ run_remove_revert_files(svn_wc__db_t *db
   const char *local_abspath;
   const char *revert_file;
   svn_node_kind_t kind;
-  
+
   /* We need a NUL-terminated path, so copy it out of the skel.  */
   local_abspath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
 
@@ -754,6 +780,9 @@ svn_wc__wq_remove_revert_files(svn_wc__d
 
 /* OP_KILLME  */
 
+/* Process the OP_KILLME work item WORK_ITEM.
+ * See svn_wc__wq_add_killme() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_killme(svn_wc__db_t *db,
            const svn_skel_t *work_item,
@@ -875,6 +904,9 @@ svn_wc__wq_add_killme(svn_wc__db_t *db,
 
 /* OP_LOGGY  */
 
+/* Process the OP_LOGGY work item WORK_ITEM.
+ * See svn_wc__wq_add_loggy() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_loggy(svn_wc__db_t *db,
           const svn_skel_t *work_item,
@@ -919,6 +951,9 @@ svn_wc__wq_add_loggy(svn_wc__db_t *db,
 
 /* OP_DELETION_POSTCOMMIT  */
 
+/* Process the OP_DELETION_POSTCOMMIT work item WORK_ITEM.
+ * See svn_wc__wq_add_deletion_postcommit() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_deletion_postcommit(svn_wc__db_t *db,
                         const svn_skel_t *work_item,
@@ -1048,10 +1083,10 @@ svn_wc__wq_add_deletion_postcommit(svn_w
 /* OP_POSTCOMMIT  */
 
 
-/* If new text was committed, then replace the text base for
- * newly-committed file NAME in directory PATH with the new
- * post-commit text base, which is waiting in the adm tmp area in
- * detranslated form.
+/* If TMP_TEXT_BASE_ABSPATH is not NULL, then replace the text base for
+ * newly-committed file FILE_ABSPATH with the new post-commit text base,
+ * TMP_TEXT_BASE_ABSPATH which is in repository-normal form (aka
+ * "detranslated" form).
  *
  * If eol and/or keyword translation would cause the working file to
  * change, then overwrite the working file with a translated copy of
@@ -1059,10 +1094,15 @@ svn_wc__wq_add_deletion_postcommit(svn_w
  * current working file -- if they are the same, do nothing, to avoid
  * clobbering timestamps unnecessarily).
  *
- * If the executable property is set, the set working file's
- * executable.
+ * Set the working file's executability according to its svn:executable
+ * property, or, if REMOVE_EXECUTABLE is TRUE, set it to not executable.
  *
- * If the working file was re-translated or had executability set,
+ * Set the working file's read-only attribute according to its properties
+ * and lock status (see svn_wc__maybe_set_read_only()), or, if
+ * REMOVE_READ_ONLY is TRUE, set it to writable.
+ *
+ * If the working file was re-translated or had its executability or
+ * read-only state changed,
  * then set OVERWROTE_WORKING to TRUE.  If the working file isn't
  * touched at all, then set to FALSE.
  *
@@ -1071,29 +1111,25 @@ svn_wc__wq_add_deletion_postcommit(svn_w
 static svn_error_t *
 install_committed_file(svn_boolean_t *overwrote_working,
                        svn_wc__db_t *db,
-                       const char *adm_abspath,
-                       const char *name,
+                       const char *file_abspath,
+                       const char *tmp_text_base_abspath,
                        svn_boolean_t remove_executable,
                        svn_boolean_t remove_read_only,
                        apr_pool_t *scratch_pool)
 {
-  const char *tmp_text_base;
-  svn_node_kind_t kind;
   svn_boolean_t same, did_set;
   const char *tmp_wfile;
   svn_boolean_t special;
-  const char *file_abspath;
 
   /* start off assuming that the working file isn't touched. */
   *overwrote_working = FALSE;
 
-  file_abspath = svn_dirent_join(adm_abspath, name, scratch_pool);
-
   /* In the commit, newlines and keywords may have been
    * canonicalized and/or contracted... Or they may not have
    * been.  It's kind of hard to know.  Here's how we find out:
    *
-   *    1. Make a translated tmp copy of the committed text base.
+   *    1. Make a translated tmp copy of the committed text base,
+   *       translated according to the versioned file's properties.
    *       Or, if no committed text base exists (the commit must have
    *       been a propchange only), make a translated tmp copy of the
    *       working file.
@@ -1106,14 +1142,22 @@ install_committed_file(svn_boolean_t *ov
    * reread the file if they don't really need to.
    */
 
-  /* Is there a tmp_text_base that needs to be installed?  */
-  SVN_ERR(svn_wc__text_base_path(&tmp_text_base, db, file_abspath, TRUE,
-                                 scratch_pool));
-  SVN_ERR(svn_io_check_path(tmp_text_base, &kind, scratch_pool));
-
+  /* Copy and translate the new base-to-be file (if found, else the working
+   * file) from repository-normal form to working form, writing a new
+   * temporary file if any translation was actually done.  Set TMP_WFILE to
+   * the translated file's path, which may be the source file's path if no
+   * translation was done.  Set SAME to indicate whether the new working
+   * text is the same as the old working text (or TRUE if it's a special
+   * file). */
   {
-    const char *tmp = (kind == svn_node_file) ? tmp_text_base : file_abspath;
+    const char *tmp
+      = (tmp_text_base_abspath != NULL) ? tmp_text_base_abspath : file_abspath;
 
+    /* Copy and translate, if necessary. The output file will be deleted at
+     * scratch_pool cleanup.
+     * ### That's not quite safe: we might rename the file and then maybe
+     * its path will get re-used for another temp file before pool clean-up.
+     * Instead, we should take responsibility for deleting it. */
     SVN_ERR(svn_wc__internal_translated_file(&tmp_wfile, tmp, db,
                                              file_abspath,
                                              SVN_WC_TRANSLATE_FROM_NF,
@@ -1148,6 +1192,8 @@ install_committed_file(svn_boolean_t *ov
         SVN_ERR(svn_io_set_file_executable(file_abspath,
                                            FALSE, /* chmod -x */
                                            FALSE, scratch_pool));
+      /* ### We should avoid setting 'overwrote_working' here if we didn't
+       * change the executability. */
       *overwrote_working = TRUE; /* entry needs wc-file's timestamp  */
     }
   else
@@ -1167,6 +1213,8 @@ install_committed_file(svn_boolean_t *ov
       if (same)
         SVN_ERR(svn_io_set_file_read_write(file_abspath, FALSE,
                                            scratch_pool));
+      /* ### We should avoid setting 'overwrote_working' here if we didn't
+       * change the read-only-ness. */
       *overwrote_working = TRUE; /* entry needs wc-file's timestamp  */
     }
   else
@@ -1180,16 +1228,26 @@ install_committed_file(svn_boolean_t *ov
     }
 
   /* Install the new text base if one is waiting. */
-  if (kind == svn_node_file)  /* tmp_text_base exists */
-    SVN_ERR(svn_wc__sync_text_base(file_abspath, scratch_pool));
+  if (tmp_text_base_abspath != NULL)
+    SVN_ERR(svn_wc__sync_text_base(file_abspath, tmp_text_base_abspath, scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
 
+/* Set the base version of the node LOCAL_ABSPATH to be the same as its
+ * working version currently is:
+ *
+ * - Remove children that are marked deleted (if it's a dir)
+ * - Install the new base props
+ * - Install the new tree state
+ * - Install the new base text (if it's a file) from TMP_TEXT_BASE_ABSPATH
+ * - Adjust the parent (if it's a dir)
+ * */
 static svn_error_t *
 log_do_committed(svn_wc__db_t *db,
                  const char *local_abspath,
+                 const char *tmp_text_base_abspath,
                  svn_revnum_t new_revision,
                  apr_time_t new_date,
                  const char *new_author,
@@ -1230,9 +1288,11 @@ log_do_committed(svn_wc__db_t *db,
 
   /*** Mark the committed item committed-to-date ***/
 
-  /* If "this dir" has been replaced (delete + add), all its
-     immmediate children *must* be either scheduled for deletion (they
-     were children of "this dir" during the "delete" phase of its
+  /* If "this dir" has been replaced (delete + add), remove those of
+     its children that are marked for deletion.
+
+     All its immmediate children *must* be either scheduled for deletion
+     (they were children of "this dir" during the "delete" phase of its
      replacement), added (they are new children of the replaced dir),
      or replaced (they are new children of the replace dir that have
      the same names as children that were present during the "delete"
@@ -1289,20 +1349,21 @@ log_do_committed(svn_wc__db_t *db,
         }
     }
 
+  /* Install the node's current working props as its new base props.
+   * Remember some details about the prop changes, for later use. */
   SVN_ERR(svn_wc__props_modified(&prop_mods, db, local_abspath, pool));
   if (prop_mods)
     {
       if (orig_entry->kind == svn_node_file)
         {
           /* Examine propchanges here before installing the new
-             propbase.  If the executable prop was -deleted-, then
-             tell install_committed_file() so.
-
-             The same applies to the needs-lock property. */
+             propbase.  If the executable prop was -deleted-, remember
+             this by setting REMOVE_EXECUTABLE so that we can later
+             tell install_committed_file() so.  The same applies to the
+             needs-lock property, remembered by setting SET_READ_WRITE. */
           int i;
           apr_array_header_t *propchanges;
 
-
           SVN_ERR(svn_wc__internal_propdiff(&propchanges, NULL, db,
                                             local_abspath, pool, pool));
           for (i = 0; i < propchanges->nelts; i++)
@@ -1319,14 +1380,15 @@ log_do_committed(svn_wc__db_t *db,
             }
         }
 
+      /* Install LOCAL_ABSPATHs working props as base props. */
       SVN_ERR(svn_wc__working_props_committed(db, local_abspath, pool));
-  }
+    }
 
+  /* If it's a file, install the tree changes and the file's text. */
   if (orig_entry->kind == svn_node_file)
     {
       svn_boolean_t overwrote_working;
       apr_finfo_t finfo;
-      const char *name = svn_dirent_basename(local_abspath, scratch_pool);
 
       SVN_ERR(svn_wc__db_global_commit(db, local_abspath,
                                        new_revision, new_date, new_author,
@@ -1347,14 +1409,13 @@ log_do_committed(svn_wc__db_t *db,
          by then will have moved to `text-base'. */
 
       if ((err = install_committed_file(&overwrote_working, db,
-                                        svn_dirent_dirname(local_abspath,
-                                                           pool),
-                                        name,
+                                        local_abspath, tmp_text_base_abspath,
                                         remove_executable, set_read_write,
                                         pool)))
         return svn_error_createf
           (SVN_ERR_WC_BAD_ADM_LOG, err,
-           _("Error replacing text-base of '%s'"), name);
+           _("Error replacing text-base of '%s'"),
+           svn_dirent_local_style(local_abspath, pool));
 
       if ((err = svn_io_stat(&finfo, local_abspath,
                              APR_FINFO_MIN | APR_FINFO_LINK, pool)))
@@ -1375,26 +1436,23 @@ log_do_committed(svn_wc__db_t *db,
           /* The working copy file hasn't been overwritten, meaning
              we need to decide which timestamp to use. */
 
-          const char *basef;
+          const char *base_abspath;
           apr_finfo_t basef_finfo;
           svn_boolean_t modified;
-          const char *base_abspath;
 
           /* If the working file was overwritten (due to re-translation)
              or touched (due to +x / -x), then use *that* textual
              timestamp instead. */
-          SVN_ERR(svn_wc__text_base_path(&basef, db,
+          SVN_ERR(svn_wc__text_base_path(&base_abspath, db,
                                          local_abspath, FALSE, pool));
-          err = svn_io_stat(&basef_finfo, basef, APR_FINFO_MIN | APR_FINFO_LINK,
+          err = svn_io_stat(&basef_finfo, base_abspath,
+                            APR_FINFO_MIN | APR_FINFO_LINK,
                             pool);
           if (err)
             return svn_error_createf
               (SVN_ERR_WC_BAD_ADM_LOG, err,
                _("Error getting 'affected time' for '%s'"),
-               svn_dirent_local_style(basef, pool));
-
-
-          SVN_ERR(svn_dirent_get_absolute(&base_abspath, basef, pool));
+               svn_dirent_local_style(base_abspath, pool));
 
           /* Verify that the working file is the same as the base file
              by comparing file sizes, then timestamps and the contents
@@ -1415,7 +1473,7 @@ log_do_committed(svn_wc__db_t *db,
                   (SVN_ERR_WC_BAD_ADM_LOG, err,
                    _("Error comparing '%s' and '%s'"),
                    svn_dirent_local_style(local_abspath, pool),
-                   svn_dirent_local_style(basef, pool));
+                   svn_dirent_local_style(base_abspath, pool));
             }
           /* If they are the same, use the working file's timestamp,
              else use the base file's timestamp. */
@@ -1431,6 +1489,8 @@ log_do_committed(svn_wc__db_t *db,
                                 pool));
     }
 
+  /* It's not a file, so it's a directory. */
+
   SVN_ERR(svn_wc__db_global_commit(db, local_abspath,
                                    new_revision, new_date, new_author,
                                    NULL /* new_checksum */,
@@ -1484,6 +1544,9 @@ log_do_committed(svn_wc__db_t *db,
 }
 
 
+/* Process the OP_POSTCOMMIT work item WORK_ITEM.
+ * See svn_wc__wq_add_postcommit() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_postcommit(svn_wc__db_t *db,
                const svn_skel_t *work_item,
@@ -1500,6 +1563,7 @@ run_postcommit(svn_wc__db_t *db,
   const svn_checksum_t *new_checksum;
   apr_hash_t *new_dav_cache;
   svn_boolean_t keep_changelist;
+  const char *tmp_text_base_abspath;
 
   local_abspath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
   new_revision = (svn_revnum_t)svn_skel__parse_int(arg1->next, scratch_pool);
@@ -1526,8 +1590,15 @@ run_postcommit(svn_wc__db_t *db,
     SVN_ERR(svn_skel__parse_proplist(&new_dav_cache, arg5->next,
                                      scratch_pool));
   keep_changelist = svn_skel__parse_int(arg5->next->next, scratch_pool) != 0;
+  if (arg5->next->next->next->len == 0)
+    tmp_text_base_abspath = NULL;
+  else
+    tmp_text_base_abspath = apr_pstrmemdup(scratch_pool,
+                                           arg5->next->next->next->data,
+                                           arg5->next->next->next->len);
 
-  SVN_ERR(log_do_committed(db, local_abspath, new_revision, new_date,
+  SVN_ERR(log_do_committed(db, local_abspath, tmp_text_base_abspath,
+                           new_revision, new_date,
                            new_author, new_checksum, new_dav_cache,
                            keep_changelist,
                            scratch_pool));
@@ -1539,6 +1610,7 @@ run_postcommit(svn_wc__db_t *db,
 svn_error_t *
 svn_wc__wq_add_postcommit(svn_wc__db_t *db,
                           const char *local_abspath,
+                          const char *tmp_text_base_abspath,
                           svn_revnum_t new_revision,
                           apr_time_t new_date,
                           const char *new_author,
@@ -1549,6 +1621,8 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
 {
   svn_skel_t *work_item = svn_skel__make_empty_list(scratch_pool);
 
+  svn_skel__prepend_str(tmp_text_base_abspath ? tmp_text_base_abspath : "",
+                        work_item, scratch_pool);
   svn_skel__prepend_int(keep_changelist, work_item, scratch_pool);
   if (new_dav_cache == NULL || apr_hash_count(new_dav_cache) == 0)
     {
@@ -1582,6 +1656,9 @@ svn_wc__wq_add_postcommit(svn_wc__db_t *
 
 /* OP_INSTALL_PROPERTIES */
 
+/* Process the OP_INSTALL_PROPERTIES work item WORK_ITEM.
+ * See svn_wc__wq_add_install_properties() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_install_properties(svn_wc__db_t *db,
                        const svn_skel_t *work_item,
@@ -1639,17 +1716,33 @@ run_install_properties(svn_wc__db_t *db,
         }
 
       {
-        svn_boolean_t in_working;
+        svn_boolean_t written = FALSE;
 
-        if (force_base_install)
-          in_working = FALSE;
-        else
-          SVN_ERR(svn_wc__prop_pristine_is_working(&in_working, db,
-                                                   local_abspath, scratch_pool));
-
-        SVN_ERR(svn_wc__db_temp_op_set_pristine_props(db, local_abspath,
-                                                      base_props, in_working,
-                                                      scratch_pool));
+        if (!force_base_install)
+          {
+            svn_error_t *err;
+
+            /* Try writing to the WORKING tree first.  */
+            err = svn_wc__db_temp_working_set_props(db, local_abspath,
+                                                    base_props,
+                                                    scratch_pool);
+            if (err)
+              {
+                if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+                  return svn_error_return(err);
+                svn_error_clear(err);
+                /* The WORKING node is not present.  */
+              }
+            else
+              {
+                /* The WORKING node is present, and we wrote the props.  */
+                written = TRUE;
+              }
+          }
+
+        if (!written)
+          SVN_ERR(svn_wc__db_temp_base_set_props(db, local_abspath,
+                                                 base_props, scratch_pool));
       }
     }
 
@@ -1717,10 +1810,14 @@ svn_wc__wq_add_install_properties(svn_wc
   return SVN_NO_ERROR;
 }
 
+
 /* ------------------------------------------------------------------------ */
 
 /* OP_DELETE */
 
+/* Process the OP_DELETE work item WORK_ITEM.
+ * See svn_wc__wq_add_delete() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
 static svn_error_t *
 run_delete(svn_wc__db_t *db,
            const svn_skel_t *work_item,
@@ -1737,25 +1834,21 @@ run_delete(svn_wc__db_t *db,
   arg = arg->next;
   kind = (int) svn_skel__parse_int(arg, scratch_pool);
   arg = arg->next;
-  was_added = (svn_boolean_t) svn_skel__parse_int(arg, scratch_pool);
+  was_added = svn_skel__parse_int(arg, scratch_pool) != 0;
   arg = arg->next;
-  was_copied = (svn_boolean_t) svn_skel__parse_int(arg, scratch_pool);
+  was_copied = svn_skel__parse_int(arg, scratch_pool) != 0;
   arg = arg->next;
-  was_replaced = (svn_boolean_t) svn_skel__parse_int(arg, scratch_pool);
+  was_replaced = svn_skel__parse_int(arg, scratch_pool) != 0;
 
   if (was_replaced && was_copied)
     {
       const char *props_base, *props_revert;
-      svn_error_t *err;
 
       SVN_ERR(svn_wc__prop_path(&props_base, local_abspath, kind,
                                 svn_wc__props_base, scratch_pool));
       SVN_ERR(svn_wc__prop_path(&props_revert, local_abspath, kind,
                                 svn_wc__props_revert, scratch_pool));
-      err = svn_io_file_rename(props_base, props_revert, scratch_pool);
-      if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
-        return svn_error_quick_wrap(err, _("Can't move source to dest"));
-      svn_error_clear(err);
+      SVN_ERR(move_if_present(props_revert, props_base, scratch_pool));
 
       if (kind != svn_wc__db_kind_dir)
         {
@@ -1763,33 +1856,22 @@ run_delete(svn_wc__db_t *db,
 
           SVN_ERR(svn_wc__text_base_path(&text_base, db, local_abspath,
                                          FALSE, scratch_pool));
-
           SVN_ERR(svn_wc__text_revert_path(&text_revert, db,
                                            local_abspath, scratch_pool));
-          err = svn_io_file_rename(text_revert, text_base, scratch_pool);
-          if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
-            return svn_error_quick_wrap(err, _("Can't move source to dest"));
-          svn_error_clear(err);
+          SVN_ERR(move_if_present(text_revert, text_base, scratch_pool));
         }
     }
   if (was_added)
     {
       const char *props_base, *props_working;
-      svn_error_t *err;
 
       SVN_ERR(svn_wc__prop_path(&props_base, local_abspath, kind,
                                 svn_wc__props_base, scratch_pool));
       SVN_ERR(svn_wc__prop_path(&props_working, local_abspath, kind,
                                 svn_wc__props_working, scratch_pool));
-      
-      err = svn_io_remove_file2(props_base, TRUE, scratch_pool);
-      if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
-        return svn_error_quick_wrap(err, _("Can't move source to dest"));
-      svn_error_clear(err);
-      err = svn_io_remove_file2(props_working, TRUE, scratch_pool);
-      if (err && !APR_STATUS_IS_ENOENT(err->apr_err))
-        return svn_error_quick_wrap(err, _("Can't move source to dest"));
-      svn_error_clear(err);
+
+      SVN_ERR(svn_io_remove_file2(props_base, TRUE, scratch_pool));
+      SVN_ERR(svn_io_remove_file2(props_working, TRUE, scratch_pool));
     }
 
   return SVN_NO_ERROR;
@@ -1822,6 +1904,224 @@ svn_wc__wq_add_delete(svn_wc__db_t *db,
 
 /* ------------------------------------------------------------------------ */
 
+/* OP_FILE_INSTALL */
+
+/* Process the OP_FILE_INSTALL work item WORK_ITEM.
+ * See svn_wc__wq_build_file_install() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
+static svn_error_t *
+run_file_install(svn_wc__db_t *db,
+                 const svn_skel_t *work_item,
+                 svn_cancel_func_t cancel_func,
+                 void *cancel_baton,
+                 apr_pool_t *scratch_pool)
+{
+  const svn_skel_t *arg1 = work_item->children->next;
+  const char *local_abspath;
+  svn_boolean_t use_commit_times;
+  svn_boolean_t record_fileinfo;
+  svn_boolean_t special;
+  svn_stream_t *src_stream;
+  svn_subst_eol_style_t style;
+  const char *eol;
+  apr_hash_t *keywords;
+  const char *temp_dir_abspath;
+  svn_stream_t *dst_stream;
+  const char *dst_abspath;
+
+  local_abspath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
+  use_commit_times = svn_skel__parse_int(arg1->next, scratch_pool) != 0;
+  record_fileinfo = svn_skel__parse_int(arg1->next->next, scratch_pool) != 0;
+
+  /* Get the pristine contents (from WORKING or BASE, as appropriate).  */
+  SVN_ERR(svn_wc__get_pristine_contents(&src_stream, db, local_abspath,
+                                        scratch_pool, scratch_pool));
+  SVN_ERR_ASSERT(src_stream != NULL);
+
+  SVN_ERR(svn_wc__get_special(&special, db, local_abspath, scratch_pool));
+  if (special)
+    {
+      /* When this stream is closed, the resulting special file will
+         atomically be created/moved into place at LOCAL_ABSPATH.  */
+      SVN_ERR(svn_subst_create_specialfile(&dst_stream, local_abspath,
+                                           scratch_pool, scratch_pool));
+
+      /* Copy the "repository normal" form of the special file into the
+         special stream.  */
+      SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
+                               cancel_func, cancel_baton,
+                               scratch_pool));
+
+      /* No need to set exec or read-only flags on special files.  */
+      return SVN_NO_ERROR;
+    }
+
+  /* Fetch all the translation bits.  */
+  SVN_ERR(svn_wc__get_eol_style(&style, &eol, db, local_abspath,
+                                scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__get_keywords(&keywords, db, local_abspath, NULL,
+                               scratch_pool, scratch_pool));
+
+  if (svn_subst_translation_required(style, eol, keywords,
+                                     FALSE /* special */,
+                                     TRUE /* force_eol_check */))
+    {
+      /* Wrap it in a translating (expanding) stream.  */
+      src_stream = svn_subst_stream_translated(src_stream, eol,
+                                               TRUE /* repair */,
+                                               keywords,
+                                               TRUE /* expand */,
+                                               scratch_pool);
+    }
+
+  /* Where is the Right Place to put a temp file in this working copy?  */
+  SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool));
+
+  /* Translate to a temporary file. We don't want the user seeing a partial
+     file, nor let them muck with it while we translate. We may also need to
+     get its TRANSLATED_SIZE before the user can monkey it.  */
+  SVN_ERR(svn_stream_open_unique(&dst_stream, &dst_abspath,
+                                 temp_dir_abspath,
+                                 svn_io_file_del_none,
+                                 scratch_pool, scratch_pool));
+
+  /* Copy from the source to the dest, translating as we go. This will also
+     close both streams.  */
+  SVN_ERR(svn_stream_copy3(src_stream, dst_stream,
+                           cancel_func, cancel_baton,
+                           scratch_pool));
+
+  /* ### post-commit feature: avoid overwrite if same as working file.  */
+
+  /* All done. Move the file into place.  */
+  /* ### fix this. we should delay the rename.  */
+  SVN_ERR(svn_io_file_rename(dst_abspath, local_abspath, scratch_pool));
+
+  /* Tweak the on-disk file according to its properties.  */
+  SVN_ERR(svn_wc__maybe_set_read_only(NULL, db, local_abspath, scratch_pool));
+  SVN_ERR(svn_wc__maybe_set_executable(NULL, db, local_abspath, scratch_pool));
+
+  if (use_commit_times)
+    {
+      apr_time_t changed_date;
+
+      SVN_ERR(svn_wc__db_read_info(
+                NULL, NULL, NULL, NULL, NULL, NULL,
+                NULL, &changed_date, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                NULL, NULL,
+                db, local_abspath,
+                scratch_pool, scratch_pool));
+
+      if (changed_date)
+        SVN_ERR(svn_io_set_file_affected_time(changed_date,
+                                              local_abspath,
+                                              scratch_pool));
+    }
+
+  if (record_fileinfo)
+    {
+      /* ### ugh. switch this over to some new wc_db APIs.  */
+
+      svn_wc_entry_t tmp_entry;
+      apr_finfo_t finfo;
+
+      /* loggy_set_entry_timestamp_from_wc()  */
+      SVN_ERR(svn_io_file_affected_time(&tmp_entry.text_time,
+                                        local_abspath,
+                                        scratch_pool));
+
+      /* loggy_set_entry_working_size_from_wc()  */
+      SVN_ERR(svn_io_stat(&finfo, local_abspath,
+                          APR_FINFO_MIN | APR_FINFO_LINK,
+                          scratch_pool));
+      tmp_entry.working_size = finfo.size;
+
+      SVN_ERR(svn_wc__entry_modify2(db, local_abspath,
+                                    svn_node_unknown, FALSE,
+                                    &tmp_entry,
+                                    SVN_WC__ENTRY_MODIFY_TEXT_TIME
+                                      | SVN_WC__ENTRY_MODIFY_WORKING_SIZE,
+                                    scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__wq_build_file_install(const svn_skel_t **work_item,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              svn_boolean_t use_commit_times,
+                              svn_boolean_t record_fileinfo,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  svn_skel_t *build_item = svn_skel__make_empty_list(result_pool);
+
+  svn_skel__prepend_int(record_fileinfo, build_item, result_pool);
+  svn_skel__prepend_int(use_commit_times, build_item, result_pool);
+  svn_skel__prepend_str(apr_pstrdup(result_pool, local_abspath),
+                        build_item, result_pool);
+  svn_skel__prepend_str(OP_FILE_INSTALL, build_item, result_pool);
+
+  /* Done. Assign to the const-ful WORK_ITEM.  */
+  *work_item = build_item;
+
+  return SVN_NO_ERROR;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/* OP_FILE_REMOVE  */
+
+/* Process the OP_FILE_REMOVE work item WORK_ITEM.
+ * See svn_wc__wq_build_file_remove() which generates this work item.
+ * Implements (struct work_item_dispatch).func. */
+static svn_error_t *
+run_file_remove(svn_wc__db_t *db,
+                 const svn_skel_t *work_item,
+                 svn_cancel_func_t cancel_func,
+                 void *cancel_baton,
+                 apr_pool_t *scratch_pool)
+{
+  const svn_skel_t *arg1 = work_item->children->next;
+  const char *local_abspath;
+
+  local_abspath = apr_pstrmemdup(scratch_pool, arg1->data, arg1->len);
+
+  /* Remove the path, no worrying if it isn't there.  */
+  return svn_error_return(svn_io_remove_file2(local_abspath, TRUE,
+                                              scratch_pool));
+}
+
+
+svn_error_t *
+svn_wc__wq_build_file_remove(const svn_skel_t **work_item,
+                             svn_wc__db_t *db,
+                             const char *local_abspath,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
+{
+  svn_skel_t *build_item = svn_skel__make_empty_list(result_pool);
+
+  svn_skel__prepend_str(apr_pstrdup(result_pool, local_abspath),
+                        build_item, result_pool);
+  svn_skel__prepend_str(OP_FILE_REMOVE, build_item, result_pool);
+
+  /* Done. Assign to the const-ful WORK_ITEM.  */
+  *work_item = build_item;
+
+  return SVN_NO_ERROR;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
 static const struct work_item_dispatch dispatch_table[] = {
   { OP_REVERT, run_revert },
   { OP_PREPARE_REVERT_FILES, run_prepare_revert_files },
@@ -1832,6 +2132,8 @@ static const struct work_item_dispatch d
   { OP_POSTCOMMIT, run_postcommit },
   { OP_INSTALL_PROPERTIES, run_install_properties },
   { OP_DELETE, run_delete },
+  { OP_FILE_INSTALL, run_file_install },
+  { OP_FILE_REMOVE, run_file_remove },
 
   /* Sentinel.  */
   { NULL }

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.h?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.h Tue Mar 30 20:57:53 2010
@@ -19,7 +19,23 @@
  *    specific language governing permissions and limitations
  *    under the License.
  * ====================================================================
- */
+ *
+ *
+ * Greg says:
+ *
+ * I think the current items are misdirected
+ * work items should NOT touch the DB
+ * the work items should be inserted into WORK_QUEUE by wc_db,
+ * meaning: workqueue.[ch] should return work items for passing to the wc_db API,
+ * which installs them during a transaction with the other work,
+ * and those items should *only* make the on-disk state match what is in the database
+ * before you rejoined the chan, I was discussing with Bert that I might rejigger the postcommit work,
+ * in order to do the prop file handling as work items,
+ * and pass those to db_global_commit for insertion as part of its transaction
+ * so that once we switch to in-db props, those work items just get deleted,
+ * (where they're simple things like: move this file to there, or delete that file)
+ * i.e. workqueue should be seriously dumb
+ * */
 
 #ifndef SVN_WC_WORKQUEUE_H
 #define SVN_WC_WORKQUEUE_H
@@ -46,6 +62,31 @@ svn_wc__wq_run(svn_wc__db_t *db,
                apr_pool_t *scratch_pool);
 
 
+/* Build a work item (returned in *WORK_ITEM) that will install the working
+   copy file at LOCAL_ABSPATH. If USE_COMMIT_TIMES is TRUE, then the newly
+   installed file will use the nodes CHANGE_DATE for the file timestamp.
+   If RECORD_FILEINFO is TRUE, then the resulting LAST_MOD_TIME and
+   TRANSLATED_SIZE will be recorded in the database.  */
+svn_error_t *
+svn_wc__wq_build_file_install(const svn_skel_t **work_item,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              svn_boolean_t use_commit_times,
+                              svn_boolean_t record_fileinfo,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool);
+
+
+/* Build a work item (returned in *WORK_ITEM) that will remove a single
+   file.  */
+svn_error_t *
+svn_wc__wq_build_file_remove(const svn_skel_t **work_item,
+                             svn_wc__db_t *db,
+                             const char *local_abspath,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool);
+
+
 /* Record a work item to revert LOCAL_ABSPATH.  */
 svn_error_t *
 svn_wc__wq_add_revert(svn_boolean_t *will_revert,
@@ -99,6 +140,7 @@ svn_wc__wq_add_deletion_postcommit(svn_w
 svn_error_t *
 svn_wc__wq_add_postcommit(svn_wc__db_t *db,
                           const char *local_abspath,
+                          const char *tmp_text_base_abspath,
                           svn_revnum_t new_revision,
                           apr_time_t new_date,
                           const char *new_author,

Modified: subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/dav_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/dav_svn.h?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/dav_svn.h Tue Mar 30 20:57:53 2010
@@ -337,23 +337,34 @@ svn_boolean_t dav_svn__get_list_parentpa
    the root_dir when the resource structure is built.
 */
 
-/* Return the special URI to be used for this resource. */
+/* Return the repo-root-relative URI of the special namespace to be used for
+ * this resource.
+ * Comes from the <SVNSpecialURI> directive. */
+/* ### Is this assumed to be URI-encoded? */
 const char *dav_svn__get_special_uri(request_rec *r);
 
-/* Return a descriptive name for the repository */
+/* Return a descriptive name for the repository.
+ * Comes from the <SVNReposName> directive. */
 const char *dav_svn__get_repo_name(request_rec *r);
 
-/* Return the URI of an XSL transform stylesheet */
+/* Return the server-relative URI of an XSL transform stylesheet.
+   Comes from the <SVNIndexXSLT> directive. */
+/* ### Is this assumed to be URI-encoded? */
 const char *dav_svn__get_xslt_uri(request_rec *r);
 
-/* Return the master URI (for mirroring) */
-const char * dav_svn__get_master_uri(request_rec *r);
-
-/* Return the activities db */
-const char * dav_svn__get_activities_db(request_rec *r);
-
-/* Return the root directory in canonicalized form */
-const char * dav_svn__get_root_dir(request_rec *r);
+/* Return the full URL of the master repository (for mirroring).
+   Comes from the <SVNMasterURI> directive. */
+/* ### Is this assumed to be URI-encoded? */
+const char *dav_svn__get_master_uri(request_rec *r);
+
+/* Return the disk path to the activities db.
+   Comes from the <SVNActivitiesDB> directive. */
+const char *dav_svn__get_activities_db(request_rec *r);
+
+/* Return the server-relative URI of the repository root.
+   Comes from the <Location> directive. */
+/* ### Is this assumed to be URI-encoded? */
+const char *dav_svn__get_root_dir(request_rec *r);
 
 
 /** For HTTP protocol v2, these are the new URIs and URI stubs
@@ -761,7 +772,7 @@ dav_svn__simple_parse_uri(dav_svn__uri_i
                           apr_pool_t *pool);
 
 
-int dav_svn__find_ns(apr_array_header_t *namespaces, const char *uri);
+int dav_svn__find_ns(const apr_array_header_t *namespaces, const char *uri);
 
 
 

Modified: subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/mirror.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/mirror.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/mirror.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/mirror.c Tue Mar 30 20:57:53 2010
@@ -35,7 +35,8 @@
    the request is ready to be proxied away.  MASTER_URI is the URI
    specified in the SVNMasterURI Apache configuration value.
    URI_SEGMENT is the URI bits relative to the repository root (but if
-   non-empty, *does* have a leading slash delimiter).  */
+   non-empty, *does* have a leading slash delimiter).
+   MASTER_URI and URI_SEGMENT are not URI-encoded. */
 static void proxy_request_fixup(request_rec *r,
                                 const char *master_uri,
                                 const char *uri_segment)

Modified: subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/util.c?rev=929279&r1=929278&r2=929279&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/util.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/util.c Tue Mar 30 20:57:53 2010
@@ -381,7 +381,7 @@ dav_svn__simple_parse_uri(dav_svn__uri_i
 
 /* ### move this into apr_xml */
 int
-dav_svn__find_ns(apr_array_header_t *namespaces, const char *uri)
+dav_svn__find_ns(const apr_array_header_t *namespaces, const char *uri)
 {
   int i;